diff --git a/.travis.yml b/.travis.yml
index 2f858ad9ca375b165b1a01fae47d8b141f02c14c..c3a6b02ca14a94c1c43eb9404b87d5ea8f8b37ee 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,6 +13,9 @@ before_install:
 install:
   - bundle install --deployment --jobs=3 --retry=3
   - npm install
+script:
+  - npm test
+  - if [ "$TRAVIS_NODE_VERSION" = "8" ]; then npm run check-broken-links; fi
 after_success:
   - if [ "$TRAVIS_NODE_VERSION" = "8" ]; then npm run coveralls; fi
 stages:
diff --git a/package-lock.json b/package-lock.json
index 54fcd2004d9b3d8abd42c24da952c41e1b5a447f..cce68c8e2e0899167c6ab84ea35dbb1a62051bf7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1492,6 +1492,57 @@
         "callsite": "1.0.0"
       }
     },
+    "bhttp": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/bhttp/-/bhttp-1.2.4.tgz",
+      "integrity": "sha1-/tDCT3ZbNa/ElAsIqzIUgT44848=",
+      "dev": true,
+      "requires": {
+        "bluebird": "^2.8.2",
+        "concat-stream": "^1.4.7",
+        "debug": "^2.1.1",
+        "dev-null": "^0.1.1",
+        "errors": "^0.2.0",
+        "extend": "^2.0.0",
+        "form-data2": "^1.0.0",
+        "form-fix-array": "^1.0.0",
+        "lodash": "^2.4.1",
+        "stream-length": "^1.0.2",
+        "string": "^3.0.0",
+        "through2-sink": "^1.0.0",
+        "through2-spy": "^1.2.0",
+        "tough-cookie": "^2.3.1"
+      },
+      "dependencies": {
+        "bluebird": {
+          "version": "2.11.0",
+          "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
+          "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=",
+          "dev": true
+        },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "extend": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend/-/extend-2.0.1.tgz",
+          "integrity": "sha1-HugBBonnOV/5RIJByYZSvHWagmA=",
+          "dev": true
+        },
+        "lodash": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
+          "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
+          "dev": true
+        }
+      }
+    },
     "binary-extensions": {
       "version": "1.11.0",
       "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
@@ -1644,6 +1695,63 @@
         "repeat-element": "^1.1.2"
       }
     },
+    "broken-link-checker": {
+      "version": "0.7.8",
+      "resolved": "https://registry.npmjs.org/broken-link-checker/-/broken-link-checker-0.7.8.tgz",
+      "integrity": "sha512-/zH4/nLMNKDeDH5nVuf/R6WYd0Yjnar1NpcdAO2+VlwjGKzJa6y42C03UO+imBSHwe6BefSkVi82fImE2Rb7yg==",
+      "dev": true,
+      "requires": {
+        "bhttp": "^1.2.1",
+        "calmcard": "~0.1.1",
+        "chalk": "^1.1.3",
+        "char-spinner": "^1.0.1",
+        "condense-whitespace": "^1.0.0",
+        "default-user-agent": "^1.0.0",
+        "errno": "~0.1.4",
+        "extend": "^3.0.0",
+        "http-equiv-refresh": "^1.0.0",
+        "humanize-duration": "^3.9.1",
+        "is-stream": "^1.0.1",
+        "is-string": "^1.0.4",
+        "limited-request-queue": "^2.0.0",
+        "link-types": "^1.1.0",
+        "maybe-callback": "^2.1.0",
+        "nopter": "~0.3.0",
+        "parse5": "^3.0.2",
+        "robot-directives": "~0.3.0",
+        "robots-txt-guard": "~0.1.0",
+        "robots-txt-parse": "~0.0.4",
+        "urlcache": "~0.7.0",
+        "urlobj": "0.0.11"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
     "browserslist": {
       "version": "3.2.8",
       "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz",
@@ -1823,6 +1931,12 @@
       "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
       "dev": true
     },
+    "calmcard": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/calmcard/-/calmcard-0.1.1.tgz",
+      "integrity": "sha1-NawrZkkrDtOa0GqJOg/25hEk5Ek=",
+      "dev": true
+    },
     "camelcase": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
@@ -1899,6 +2013,12 @@
         "supports-color": "^5.3.0"
       }
     },
+    "char-spinner": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/char-spinner/-/char-spinner-1.0.1.tgz",
+      "integrity": "sha1-5upnvSR+EHESmDt6sEee02KAAIE=",
+      "dev": true
+    },
     "character-entities": {
       "version": "1.2.2",
       "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz",
@@ -2037,6 +2157,23 @@
         "restore-cursor": "^2.0.0"
       }
     },
+    "cli-table": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz",
+      "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=",
+      "dev": true,
+      "requires": {
+        "colors": "1.0.3"
+      },
+      "dependencies": {
+        "colors": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+          "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
+          "dev": true
+        }
+      }
+    },
     "cli-width": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
@@ -2148,6 +2285,34 @@
         "delayed-stream": "~1.0.0"
       }
     },
+    "combined-stream2": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/combined-stream2/-/combined-stream2-1.1.2.tgz",
+      "integrity": "sha1-9uFLegFWZvjHsKH6xQYkAWSsNXA=",
+      "dev": true,
+      "requires": {
+        "bluebird": "^2.8.1",
+        "debug": "^2.1.1",
+        "stream-length": "^1.0.1"
+      },
+      "dependencies": {
+        "bluebird": {
+          "version": "2.11.0",
+          "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
+          "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=",
+          "dev": true
+        },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
     "commander": {
       "version": "2.15.1",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
@@ -2202,6 +2367,12 @@
         "typedarray": "^0.0.6"
       }
     },
+    "condense-whitespace": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/condense-whitespace/-/condense-whitespace-1.0.0.tgz",
+      "integrity": "sha1-g3bZjvAo5sss0kaOKM5CxcZasak=",
+      "dev": true
+    },
     "configstore": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
@@ -2281,6 +2452,12 @@
       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
       "dev": true
     },
+    "corser": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
+      "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=",
+      "dev": true
+    },
     "cosmiconfig": {
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz",
@@ -2475,6 +2652,15 @@
         }
       }
     },
+    "default-user-agent": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/default-user-agent/-/default-user-agent-1.0.0.tgz",
+      "integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=",
+      "dev": true,
+      "requires": {
+        "os-name": "~1.0.3"
+      }
+    },
     "define-properties": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
@@ -2613,6 +2799,12 @@
         "repeating": "^2.0.0"
       }
     },
+    "dev-null": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz",
+      "integrity": "sha1-WiBc48Ky73e2I41roXnrdMag6Bg=",
+      "dev": true
+    },
     "di": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
@@ -2754,6 +2946,26 @@
         "jsbn": "~0.1.0"
       }
     },
+    "ecstatic": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.2.0.tgz",
+      "integrity": "sha512-Goilx/2cfU9vvfQjgtNgc2VmJAD8CasQ6rZDqCd2u4Hsyd/qFET6nBf60jiHodevR3nl3IGzNKtrzPXWP88utQ==",
+      "dev": true,
+      "requires": {
+        "he": "^1.1.1",
+        "mime": "^1.4.1",
+        "minimist": "^1.1.0",
+        "url-join": "^2.0.2"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        }
+      }
+    },
     "ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -2846,6 +3058,21 @@
       "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
       "dev": true
     },
+    "eol": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/eol/-/eol-0.2.0.tgz",
+      "integrity": "sha1-L22whqJDpG4+Xb0OE0Ncfr6/Cd0=",
+      "dev": true
+    },
+    "errno": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+      "dev": true,
+      "requires": {
+        "prr": "~1.0.1"
+      }
+    },
     "error-ex": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -2855,6 +3082,12 @@
         "is-arrayish": "^0.2.1"
       }
     },
+    "errors": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/errors/-/errors-0.2.0.tgz",
+      "integrity": "sha1-D1Hoidqj4RsZ5xhtEfEEqmbrJAM=",
+      "dev": true
+    },
     "es-abstract": {
       "version": "1.12.0",
       "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
@@ -4141,6 +4374,55 @@
         "mime-types": "^2.1.12"
       }
     },
+    "form-data2": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/form-data2/-/form-data2-1.0.3.tgz",
+      "integrity": "sha1-y6XiNgGmlE2Vq31xEf+Tl6XLKk0=",
+      "dev": true,
+      "requires": {
+        "bluebird": "^2.8.2",
+        "combined-stream2": "^1.0.2",
+        "debug": "^2.1.1",
+        "lodash": "^2.4.1",
+        "mime": "^1.2.11",
+        "uuid": "^2.0.1"
+      },
+      "dependencies": {
+        "bluebird": {
+          "version": "2.11.0",
+          "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
+          "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=",
+          "dev": true
+        },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "lodash": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
+          "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
+          "dev": true
+        },
+        "uuid": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
+          "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=",
+          "dev": true
+        }
+      }
+    },
+    "form-fix-array": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/form-fix-array/-/form-fix-array-1.0.0.tgz",
+      "integrity": "sha1-oTR6R+UxF6t7zb8+Lz7JHGZ2m8g=",
+      "dev": true
+    },
     "fragment-cache": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -5340,6 +5622,12 @@
         "sntp": "1.x.x"
       }
     },
+    "he": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
+      "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+      "dev": true
+    },
     "hipchat-notifier": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz",
@@ -5420,6 +5708,12 @@
         "readable-stream": "^2.0.2"
       }
     },
+    "http-equiv-refresh": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-1.0.0.tgz",
+      "integrity": "sha1-jsU4hmBCvl8/evpzfRmNlL6xsHs=",
+      "dev": true
+    },
     "http-errors": {
       "version": "1.6.3",
       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
@@ -5453,6 +5747,30 @@
         "debug": "3.1.0"
       }
     },
+    "http-server": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz",
+      "integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==",
+      "dev": true,
+      "requires": {
+        "colors": "1.0.3",
+        "corser": "~2.0.0",
+        "ecstatic": "^3.0.0",
+        "http-proxy": "^1.8.1",
+        "opener": "~1.4.0",
+        "optimist": "0.6.x",
+        "portfinder": "^1.0.13",
+        "union": "~0.4.3"
+      },
+      "dependencies": {
+        "colors": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+          "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
+          "dev": true
+        }
+      }
+    },
     "http-signature": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@@ -5490,6 +5808,12 @@
         "debug": "^3.1.0"
       }
     },
+    "humanize-duration": {
+      "version": "3.15.0",
+      "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.15.0.tgz",
+      "integrity": "sha512-FTR8w/wZhj4AJkao99vMqCMRwE1j7q0JI+JjQBe6C26LRgg9JLgmXbr9VvBYi3/wx8WVC2ge+eNJ/ZG5nM5whg==",
+      "dev": true
+    },
     "iconv-lite": {
       "version": "0.4.23",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
@@ -5710,6 +6034,12 @@
         "binary-extensions": "^1.0.0"
       }
     },
+    "is-browser": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.0.1.tgz",
+      "integrity": "sha1-i/C695mpxi/Z3lvO5M8zl8PnUpo=",
+      "dev": true
+    },
     "is-buffer": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -5899,6 +6229,12 @@
       "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
       "dev": true
     },
+    "is-object": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
+      "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
+      "dev": true
+    },
     "is-odd": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz",
@@ -6035,6 +6371,12 @@
       "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
       "dev": true
     },
+    "is-string": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz",
+      "integrity": "sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ=",
+      "dev": true
+    },
     "is-supported-regexp-flag": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz",
@@ -6098,6 +6440,12 @@
       "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=",
       "dev": true
     },
+    "isbot": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/isbot/-/isbot-2.1.2.tgz",
+      "integrity": "sha512-y98+gTTU11BIKkyP8QvohQpURrRVH5nwQryw5GjyJIeWP7Q4NAnpBHSPHa6Tp1tcLj035YySYTO6XEye6SCy4w==",
+      "dev": true
+    },
     "isemail": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.1.2.tgz",
@@ -6957,6 +7305,22 @@
         "resolve": "^1.1.7"
       }
     },
+    "limited-request-queue": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/limited-request-queue/-/limited-request-queue-2.0.0.tgz",
+      "integrity": "sha1-FMfBILE4BgsZoqEDCrr2aTVyZQ0=",
+      "dev": true,
+      "requires": {
+        "is-browser": "^2.0.1",
+        "parse-domain": "~0.2.0"
+      }
+    },
+    "link-types": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/link-types/-/link-types-1.1.0.tgz",
+      "integrity": "sha1-r2XlnbUucMH/sYrEw8sFa/55aDA=",
+      "dev": true
+    },
     "load-json-file": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
@@ -7444,6 +7808,12 @@
       "integrity": "sha512-3Zs9P/0zzwTob2pdgT0CHZuMbnSUSp8MB1bddfm+HDmnFWHGT4jvEZRf+2RuPoa+cjdn/z25SEt5gFTqdhvJAg==",
       "dev": true
     },
+    "maybe-callback": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/maybe-callback/-/maybe-callback-2.1.0.tgz",
+      "integrity": "sha1-ivoLp7aRp6sSPn8S9l4yu10fgkM=",
+      "dev": true
+    },
     "mdast-util-compact": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz",
@@ -8475,6 +8845,85 @@
         "abbrev": "1"
       }
     },
+    "nopter": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/nopter/-/nopter-0.3.0.tgz",
+      "integrity": "sha1-uWkOb6uPJWs35OfM0j4rOEUMxx8=",
+      "dev": true,
+      "requires": {
+        "caller-path": "~0.1.0",
+        "camelcase": "^1.0.2",
+        "chalk": "~0.5.1",
+        "cli-table": "~0.3.1",
+        "eol": "~0.2.0",
+        "nopt": "^3.0.1",
+        "object-assign": "^2.0.0",
+        "splitargs": "~0.0.3"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "0.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
+          "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz",
+          "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=",
+          "dev": true
+        },
+        "camelcase": {
+          "version": "1.2.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+          "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "0.5.1",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz",
+          "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^1.1.0",
+            "escape-string-regexp": "^1.0.0",
+            "has-ansi": "^0.1.0",
+            "strip-ansi": "^0.3.0",
+            "supports-color": "^0.2.0"
+          }
+        },
+        "has-ansi": {
+          "version": "0.1.0",
+          "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz",
+          "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^0.2.0"
+          }
+        },
+        "object-assign": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz",
+          "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "0.3.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz",
+          "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^0.2.1"
+          }
+        },
+        "supports-color": {
+          "version": "0.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz",
+          "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=",
+          "dev": true
+        }
+      }
+    },
     "normalize-package-data": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
@@ -8834,6 +9283,12 @@
         }
       }
     },
+    "opener": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz",
+      "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=",
+      "dev": true
+    },
     "opn": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz",
@@ -8893,6 +9348,16 @@
         "mem": "^1.1.0"
       }
     },
+    "os-name": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz",
+      "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=",
+      "dev": true,
+      "requires": {
+        "osx-release": "^1.0.0",
+        "win-release": "^1.0.0"
+      }
+    },
     "os-tmpdir": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
@@ -8909,6 +9374,23 @@
         "os-tmpdir": "^1.0.0"
       }
     },
+    "osx-release": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz",
+      "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=",
+      "dev": true,
+      "requires": {
+        "minimist": "^1.1.0"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        }
+      }
+    },
     "output-file-sync": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz",
@@ -8993,6 +9475,12 @@
         "semver": "^5.1.0"
       }
     },
+    "parse-domain": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-0.2.2.tgz",
+      "integrity": "sha1-GImJseLnOYv/PE9P19yhV+tR+sE=",
+      "dev": true
+    },
     "parse-entities": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.2.tgz",
@@ -9045,6 +9533,15 @@
       "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
       "dev": true
     },
+    "parse5": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+      "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+      "dev": true,
+      "requires": {
+        "@types/node": "*"
+      }
+    },
     "parseqs": {
       "version": "0.0.5",
       "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
@@ -9221,6 +9718,34 @@
       "integrity": "sha1-FDj5jQRqz3tNeM1QK/QYrGTU8JU=",
       "dev": true
     },
+    "portfinder": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz",
+      "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=",
+      "dev": true,
+      "requires": {
+        "async": "^1.5.2",
+        "debug": "^2.2.0",
+        "mkdirp": "0.5.x"
+      },
+      "dependencies": {
+        "async": {
+          "version": "1.5.2",
+          "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+          "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+          "dev": true
+        },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
     "posix-character-classes": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@@ -9974,6 +10499,12 @@
       "dev": true,
       "optional": true
     },
+    "prr": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+      "dev": true
+    },
     "ps-tree": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz",
@@ -10587,6 +11118,61 @@
         "glob": "^7.0.5"
       }
     },
+    "robot-directives": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/robot-directives/-/robot-directives-0.3.0.tgz",
+      "integrity": "sha1-F0+x/8KpuXh3MB6HyJs5X0KdH2U=",
+      "dev": true,
+      "requires": {
+        "isbot": "^2.0.0",
+        "useragent": "^2.1.8"
+      }
+    },
+    "robots-txt-guard": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/robots-txt-guard/-/robots-txt-guard-0.1.1.tgz",
+      "integrity": "sha512-6+nGkE6c2dI9/dmhmNcoMKVwJxlA6sgN/XNo0rm6LLdA0hnj4YkpgrZdhMPl58gJkAqeiHlf4+8tJcLM1tv1Ew==",
+      "dev": true
+    },
+    "robots-txt-parse": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/robots-txt-parse/-/robots-txt-parse-0.0.4.tgz",
+      "integrity": "sha1-99HzI/eZIdfpxsS70lBI9umBDXE=",
+      "dev": true,
+      "requires": {
+        "bluebird": "^2.3.5",
+        "split": "^0.3.0",
+        "stream-combiner": "^0.2.1",
+        "through": "^2.3.4"
+      },
+      "dependencies": {
+        "bluebird": {
+          "version": "2.11.0",
+          "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
+          "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=",
+          "dev": true
+        },
+        "split": {
+          "version": "0.3.3",
+          "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
+          "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
+          "dev": true,
+          "requires": {
+            "through": "2"
+          }
+        },
+        "stream-combiner": {
+          "version": "0.2.2",
+          "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz",
+          "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=",
+          "dev": true,
+          "requires": {
+            "duplexer": "~0.1.1",
+            "through": "~2.3.4"
+          }
+        }
+      }
+    },
     "rollup": {
       "version": "0.61.1",
       "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.61.1.tgz",
@@ -11340,6 +11926,12 @@
         "extend-shallow": "^3.0.0"
       }
     },
+    "splitargs": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/splitargs/-/splitargs-0.0.7.tgz",
+      "integrity": "sha1-/p965lc3GzOxDLgNoUPPgknPazs=",
+      "dev": true
+    },
     "sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -11420,6 +12012,23 @@
         "duplexer": "~0.1.1"
       }
     },
+    "stream-length": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz",
+      "integrity": "sha1-gnfzy+5JpNqrz9tOL0qbXp8snwA=",
+      "dev": true,
+      "requires": {
+        "bluebird": "^2.6.2"
+      },
+      "dependencies": {
+        "bluebird": {
+          "version": "2.11.0",
+          "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
+          "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=",
+          "dev": true
+        }
+      }
+    },
     "streamroller": {
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz",
@@ -11432,6 +12041,12 @@
         "readable-stream": "^2.3.0"
       }
     },
+    "string": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/string/-/string-3.3.3.tgz",
+      "integrity": "sha1-XqIRzZLSKOGEKUmQpsyXs2anfLA=",
+      "dev": true
+    },
     "string-width": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -12209,6 +12824,84 @@
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
       "dev": true
     },
+    "through2": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz",
+      "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=",
+      "dev": true,
+      "requires": {
+        "readable-stream": "~1.0.17",
+        "xtend": "~3.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "1.0.34",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.1",
+            "isarray": "0.0.1",
+            "string_decoder": "~0.10.x"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+          "dev": true
+        },
+        "xtend": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz",
+          "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=",
+          "dev": true
+        }
+      }
+    },
+    "through2-sink": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/through2-sink/-/through2-sink-1.0.0.tgz",
+      "integrity": "sha1-XxBruh1zMNrTy6XAqxhjkjJWw5k=",
+      "dev": true,
+      "requires": {
+        "through2": "~0.5.1",
+        "xtend": "~3.0.0"
+      },
+      "dependencies": {
+        "xtend": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz",
+          "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=",
+          "dev": true
+        }
+      }
+    },
+    "through2-spy": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/through2-spy/-/through2-spy-1.2.0.tgz",
+      "integrity": "sha1-nIkcqcpA4eHkzzHhrFf5TMnSSMs=",
+      "dev": true,
+      "requires": {
+        "through2": "~0.5.1",
+        "xtend": "~3.0.0"
+      },
+      "dependencies": {
+        "xtend": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz",
+          "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=",
+          "dev": true
+        }
+      }
+    },
     "thunkify": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz",
@@ -12561,6 +13254,23 @@
         "x-is-string": "^0.1.0"
       }
     },
+    "union": {
+      "version": "0.4.6",
+      "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz",
+      "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=",
+      "dev": true,
+      "requires": {
+        "qs": "~2.3.3"
+      },
+      "dependencies": {
+        "qs": {
+          "version": "2.3.3",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz",
+          "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=",
+          "dev": true
+        }
+      }
+    },
     "union-value": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
@@ -12753,6 +13463,12 @@
       "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
       "dev": true
     },
+    "url-join": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz",
+      "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=",
+      "dev": true
+    },
     "url-parse-lax": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
@@ -12762,6 +13478,26 @@
         "prepend-http": "^1.0.1"
       }
     },
+    "urlcache": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/urlcache/-/urlcache-0.7.0.tgz",
+      "integrity": "sha512-xOW4t6wJDT07+VunsHwePemyXXRidCSOZ/1RIILJi2XnB+81FA5H0MRvS63/7joTWjGLajcJJGvR5odpbkV6hw==",
+      "dev": true,
+      "requires": {
+        "urlobj": "0.0.11"
+      }
+    },
+    "urlobj": {
+      "version": "0.0.11",
+      "resolved": "https://registry.npmjs.org/urlobj/-/urlobj-0.0.11.tgz",
+      "integrity": "sha512-Ncck0WWtuFBbZhSYwKjK1AU2V51V98P/KHUPkaEc+mFy4xkpAHFNyVQT+S5SgtsJAr94e4wiKUucJSfasV2kBw==",
+      "dev": true,
+      "requires": {
+        "is-object": "^1.0.1",
+        "is-string": "^1.0.4",
+        "object-assign": "^4.1.1"
+      }
+    },
     "use": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz",
@@ -12932,6 +13668,15 @@
         "string-width": "^2.1.1"
       }
     },
+    "win-release": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz",
+      "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=",
+      "dev": true,
+      "requires": {
+        "semver": "^5.0.1"
+      }
+    },
     "window-size": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
diff --git a/package.json b/package.json
index 4170336616779981e606e31bcbc42ff75bfad330..0ace217ea05c4cfbf7e963af7a1ed16c419dd715 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,10 @@
     "Twitter, Inc."
   ],
   "scripts": {
+    "blc": "blc --exclude-external --filter-level 3 --get --ordered --recursive --host-requests 4 --input http://localhost:3000/",
+    "http-server": "http-server --silent -p 3000",
     "bundlesize": "bundlesize",
+    "check-broken-links": "npm-run-all --parallel --race \"http-server -- _gh_pages/\" blc",
     "css": "npm-run-all --parallel css-lint* css-compile* --sequential css-prefix* css-minify*",
     "css-main": "npm-run-all --parallel css-lint css-compile --sequential css-prefix css-minify",
     "css-docs": "npm-run-all --parallel css-lint-docs css-compile-docs --sequential css-prefix-docs css-minify-docs",
@@ -49,7 +52,7 @@
     "js-test-karma-old": "cross-env USE_OLD_JQUERY=true npm run js-test-karma",
     "js-test-karma-bundle": "cross-env karma start js/tests/karma-bundle.conf.js",
     "js-test-karma-bundle-old": "cross-env USE_OLD_JQUERY=true npm run js-test-karma-bundle",
-    "js-test-cloud": "ruby -r webrick -e \"s = WEBrick::HTTPServer.new(:Port => 3000, :DocumentRoot => Dir.pwd, :Logger => WEBrick::Log.new('/dev/null'), :AccessLog => []); trap('INT') { s.shutdown }; s.start\" & node build/saucelabs-unit-test.js",
+    "js-test-cloud": "npm-run-all --parallel --race http-server saucelabs-test",
     "coveralls": "shx cat js/coverage/lcov.info | coveralls",
     "docs": "npm-run-all --parallel css-docs js-docs --sequential docs-compile docs-lint",
     "docs-compile": "bundle exec jekyll build",
@@ -65,6 +68,7 @@
     "release-sri": "node build/generate-sri.js",
     "release-version": "node build/change-version.js",
     "release-zip": "cd dist/ && zip -r9 bootstrap-$npm_package_version-dist.zip * && shx mv bootstrap-$npm_package_version-dist.zip ..",
+    "saucelabs-test": "node build/saucelabs-unit-test.js",
     "dist": "npm-run-all --parallel css js",
     "test": "npm-run-all dist js-test docs-compile docs-lint bundlesize",
     "watch": "npm-run-all --parallel watch-css watch-js",
@@ -95,6 +99,7 @@
     "babel-eslint": "^8.2.3",
     "babel-plugin-istanbul": "^4.1.6",
     "babel-plugin-transform-es2015-modules-strip": "^0.1.1",
+    "broken-link-checker": "^0.7.8",
     "bundlesize": "^0.15.3",
     "clean-css-cli": "^4.1.11",
     "coveralls": "^3.0.1",
@@ -103,6 +108,7 @@
     "eslint-plugin-compat": "^2.4.0",
     "glob": "^7.1.2",
     "htmllint-cli": "^0.0.7",
+    "http-server": "^0.11.1",
     "jsunitsaucelabs": "^1.3.2",
     "karma": "^2.0.3",
     "karma-chrome-launcher": "^2.2.0",