diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000000000000000000000000000000000..cdb36c1b4662559d2880d7a1ae9e65ca7497f47e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,11 @@
+# http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[{*.js,*.json,*.yml}]
+indent_size = 2
+indent_style = space
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000000000000000000000000000000000000..76b1021d09a5774679c815f83d1c9a4bccf21c28
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,3 @@
+.nyc_output
+coverage
+node_modules
diff --git a/.eslintrc.yml b/.eslintrc.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c1475b20ba410e55c0d51b9c636e44a995845c9a
--- /dev/null
+++ b/.eslintrc.yml
@@ -0,0 +1,9 @@
+root: true
+extends: eslint:recommended
+env:
+  node: true
+rules:
+  eol-last: error
+  indent: ["error", 2, { "SwitchCase": 1 }]
+  no-mixed-spaces-and-tabs: error
+  no-trailing-spaces: error
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 138b0e7722a418cc606197f92a3e78b181f72aa2..0000000000000000000000000000000000000000
--- a/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.nyc_output/
-coverage/
-node_modules/
-npm-debug.log
-package-log.json
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 1b7ca0527b7a25332e060a29f1db64c16efeadd9..0000000000000000000000000000000000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-language: node_js
-node_js:
-  - "0.8"
-  - "0.10"
-  - "0.12"
-  - "1.8"
-  - "2.4"
-  - "3.3"
-  - "4.8"
-  - "5.12"
-  - "6.11"
-  - "7.10"
-  - "8.4"
-sudo: false
-cache:
-  directories:
-    - node_modules
-before_install:
-  # Skip updating shrinkwrap / lock
-  - "npm config set shrinkwrap false"
-  # Setup Node.js version-specific dependencies
-  - "test $TRAVIS_NODE_VERSION != '0.8' || npm rm --save-dev nyc"
-  # Update Node.js modules
-  - "test ! -d node_modules || npm prune"
-  - "test ! -d node_modules || npm rebuild"
-script:
-  # Run test script, depending on nyc install
-  - "test ! -z $(npm -ps ls nyc) || npm test"
-  - "test   -z $(npm -ps ls nyc) || npm run-script test-ci"
-after_script:
-  # Report coverage
-  - "test -d .nyc_output && npm install coveralls@2 && nyc report --reporter=text-lcov | coveralls"
diff --git a/History.md b/History.md
index 13d463ab1557176e38dde21b613131b6eec28b01..cf6a5bb9cf0cb1dd3f5a94d5dde1797ef8188be8 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,8 @@
+3.1.0 / 2019-01-22
+==================
+
+  * Add petabyte (`pb`) support
+
 3.0.0 / 2017-08-31
 ==================
 
diff --git a/Readme.md b/Readme.md
index 9b53745d1b92062abcf68b8145f640c8f93e1b22..6ad1ec6e2a57a90493527881b969952b4d4ec105 100644
--- a/Readme.md
+++ b/Readme.md
@@ -83,6 +83,7 @@ Supported units and abbreviations are as follows and are case-insensitive:
   * `mb` for megabytes
   * `gb` for gigabytes
   * `tb` for terabytes
+  * `pb` for petabytes
 
 The units are in powers of two, not ten. This means 1kb = 1024b according to this parser.
 
@@ -108,18 +109,18 @@ bytes('1024');
 // output: 1024
 
 bytes(1024);
-// output: 1024
+// output: 1KB
 ```
 
 ## License 
 
 [MIT](LICENSE)
 
-[downloads-image]: https://img.shields.io/npm/dm/bytes.svg
+[coveralls-image]: https://badgen.net/coveralls/c/github/visionmedia/bytes.js/master
+[coveralls-url]: https://coveralls.io/r/visionmedia/bytes.js?branch=master
+[downloads-image]: https://badgen.net/npm/dm/bytes
 [downloads-url]: https://npmjs.org/package/bytes
-[npm-image]: https://img.shields.io/npm/v/bytes.svg
+[npm-image]: https://badgen.net/npm/node/bytes
 [npm-url]: https://npmjs.org/package/bytes
-[travis-image]: https://img.shields.io/travis/visionmedia/bytes.js/master.svg
+[travis-image]: https://badgen.net/travis/visionmedia/bytes.js/master
 [travis-url]: https://travis-ci.org/visionmedia/bytes.js
-[coveralls-image]: https://img.shields.io/coveralls/visionmedia/bytes.js/master.svg
-[coveralls-url]: https://coveralls.io/r/visionmedia/bytes.js?branch=master
diff --git a/index.js b/index.js
index 1e39afd1d961e36efc4bda8377a00e1169c0c7b7..4975bfb0c9f6f67e151c22dab71a733b7a6c2d8d 100644
--- a/index.js
+++ b/index.js
@@ -30,10 +30,11 @@ var map = {
   kb: 1 << 10,
   mb: 1 << 20,
   gb: 1 << 30,
-  tb: ((1 << 30) * 1024)
+  tb: Math.pow(1024, 4),
+  pb: Math.pow(1024, 5),
 };
 
-var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb)$/i;
+var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;
 
 /**
  * Convert the given value in bytes into a string or parse to string to an integer in bytes.
@@ -93,7 +94,9 @@ function format(value, options) {
   var unit = (options && options.unit) || '';
 
   if (!unit || !map[unit.toLowerCase()]) {
-    if (mag >= map.tb) {
+    if (mag >= map.pb) {
+      unit = 'PB';
+    } else if (mag >= map.tb) {
       unit = 'TB';
     } else if (mag >= map.gb) {
       unit = 'GB';
diff --git a/package.json b/package.json
index 219329659b05f32789da0b4cb92b2165de37e37e..72ee63d03b597307b8fcecd7250fe7a3a772ab46 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "bytes",
   "description": "Utility to parse a string bytes to bytes and vice-versa",
-  "version": "3.0.0",
+  "version": "3.1.0",
   "author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)",
   "contributors": [
     "Jed Watson <jed.watson@me.com>",
@@ -19,8 +19,9 @@
   ],
   "repository": "visionmedia/bytes.js",
   "devDependencies": {
-    "mocha": "2.5.3",
-    "nyc": "10.3.2"
+    "eslint": "5.12.1",
+    "mocha": "5.2.0",
+    "nyc": "13.1.0"
   },
   "files": [
     "History.md",
@@ -32,6 +33,7 @@
     "node": ">= 0.8"
   },
   "scripts": {
+    "lint": "eslint .",
     "test": "mocha --check-leaks --reporter spec",
     "test-ci": "nyc --reporter=text npm test",
     "test-cov": "nyc --reporter=html --reporter=text npm test"
diff --git a/test/.eslintrc.yml b/test/.eslintrc.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9808c3b2b6602da61eb4afcb4caf33368e3e2bd4
--- /dev/null
+++ b/test/.eslintrc.yml
@@ -0,0 +1,2 @@
+env:
+  mocha: true
diff --git a/test/byte-format.js b/test/byte-format.js
index 0975177c6c8343cccd0416f3ab57eae74fbc1d9c..996eb1af9d6d1f744ef775a3933a981ac4908b3f 100644
--- a/test/byte-format.js
+++ b/test/byte-format.js
@@ -4,12 +4,13 @@ var assert = require('assert');
 var bytes = require('..');
 
 describe('Test byte format function', function(){
+  var pb = Math.pow(1024, 5);
   var tb = (1 << 30) * 1024,
-      gb = 1 << 30,
-      mb = 1 << 20,
-      kb = 1 << 10;
+    gb = 1 << 30,
+    mb = 1 << 20,
+    kb = 1 << 10;
 
-  it('Should return null if input invalid', function(){
+  it('Should return null if input is invalid', function(){
     assert.strictEqual(bytes.format(undefined), null);
     assert.strictEqual(bytes.format(null), null);
     assert.strictEqual(bytes.format(true), null);
@@ -52,15 +53,22 @@ describe('Test byte format function', function(){
     assert.equal(bytes.format(2 * tb).toLowerCase(), '2tb');
   });
 
+  it('Should convert numbers >= 1 125 899 906 842 624 to pb string', function(){
+    assert.equal(bytes.format(pb).toLowerCase(), '1pb');
+    assert.equal(bytes.format(-pb).toLowerCase(), '-1pb');
+    assert.equal(bytes.format(2 * pb).toLowerCase(), '2pb');
+  });
+
   it('Should return standard case', function(){
     assert.equal(bytes.format(10), '10B');
     assert.equal(bytes.format(kb), '1KB');
     assert.equal(bytes.format(mb), '1MB');
     assert.equal(bytes.format(gb), '1GB');
     assert.equal(bytes.format(tb), '1TB');
+    assert.equal(bytes.format(pb), '1PB');
   });
 
-  it('Support custom thousands separator', function(){
+  it('Should support custom thousands separator', function(){
     assert.equal(bytes.format(1000).toLowerCase(), '1000b');
     assert.equal(bytes.format(1000, {thousandsSeparator: ''}).toLowerCase(), '1000b');
     assert.equal(bytes.format(1000, {thousandsSeparator: null}).toLowerCase(), '1000b');
@@ -69,7 +77,7 @@ describe('Test byte format function', function(){
     assert.equal(bytes.format(1000, {thousandsSeparator: ' '}).toLowerCase(), '1 000b');
   });
 
-  it('Should custom unit separator', function(){
+  it('Should support custom unit separator', function(){
     assert.equal(bytes.format(1024), '1KB');
     assert.equal(bytes.format(1024, {unitSeparator: ''}), '1KB');
     assert.equal(bytes.format(1024, {unitSeparator: null}), '1KB');
diff --git a/test/byte-parse.js b/test/byte-parse.js
index e4efadc7d97db5d37fbd493b6e314419c80ad4e4..88916029b812c925ed225d01c0a1d7b77fa71b38 100644
--- a/test/byte-parse.js
+++ b/test/byte-parse.js
@@ -4,7 +4,7 @@ var assert = require('assert');
 var bytes = require('..');
 
 describe('Test byte parse function', function(){
-  it('Should return null if input invalid', function(){
+  it('Should return null if input is invalid', function(){
     assert.strictEqual(bytes.parse(undefined), null);
     assert.strictEqual(bytes.parse(null), null);
     assert.strictEqual(bytes.parse(true), null);
@@ -69,6 +69,23 @@ describe('Test byte parse function', function(){
     assert.equal(bytes.parse('1.5tB'), 1.5 * Math.pow(1024, 4));
   });
 
+  it('Should parse PB', function(){
+    assert.equal(bytes.parse('1pb'), 1 * Math.pow(1024, 5));
+    assert.equal(bytes.parse('1PB'), 1 * Math.pow(1024, 5));
+    assert.equal(bytes.parse('1Pb'), 1 * Math.pow(1024, 5));
+    assert.equal(bytes.parse('1pB'), 1 * Math.pow(1024, 5));
+
+    assert.equal(bytes.parse('0.5pb'), 0.5 * Math.pow(1024, 5));
+    assert.equal(bytes.parse('0.5PB'), 0.5 * Math.pow(1024, 5));
+    assert.equal(bytes.parse('0.5Pb'), 0.5 * Math.pow(1024, 5));
+    assert.equal(bytes.parse('0.5pB'), 0.5 * Math.pow(1024, 5));
+
+    assert.equal(bytes.parse('1.5pb'), 1.5 * Math.pow(1024, 5));
+    assert.equal(bytes.parse('1.5PB'), 1.5 * Math.pow(1024, 5));
+    assert.equal(bytes.parse('1.5Pb'), 1.5 * Math.pow(1024, 5));
+    assert.equal(bytes.parse('1.5pB'), 1.5 * Math.pow(1024, 5));
+  });
+
   it('Should assume bytes when no units', function(){
     assert.equal(bytes.parse('0'), 0);
     assert.equal(bytes.parse('-1'), -1);
diff --git a/test/bytes.js b/test/bytes.js
index 64e3c37f6fb3a691a6891e897993488742095364..80bba2f0f5841bcdfa623ec305f5f445579adddb 100644
--- a/test/bytes.js
+++ b/test/bytes.js
@@ -8,7 +8,7 @@ describe('Test constructor', function(){
     assert.equal(typeof bytes, 'function');
   });
 
-  it('Should return null if input invalid', function(){
+  it('Should return null if input is invalid', function(){
     assert.strictEqual(bytes(undefined), null);
     assert.strictEqual(bytes(null), null);
     assert.strictEqual(bytes(true), null);
@@ -18,18 +18,18 @@ describe('Test constructor', function(){
     assert.strictEqual(bytes({}), null);
   });
 
-  it('Shoud be able to parse a string into a number', function(){
-    // This function is testes more accurately in another test suite
+  it('Should be able to parse a string into a number', function(){
+    // This function is tested more accurately in another test suite
     assert.equal(bytes('1KB'), 1024);
   });
 
   it('Should convert a number into a string', function(){
-    // This function is testes more accurately in another test suite
+    // This function is tested more accurately in another test suite
     assert.equal(bytes(1024), '1KB');
   });
 
   it('Should convert a number into a string with options', function(){
-    // This function is testes more accurately in another test suite
+    // This function is tested more accurately in another test suite
     assert.equal(bytes(1000, {thousandsSeparator: ' '}), '1 000B');
   });
 });