diff --git a/frontend/components/badge-examples.js b/frontend/components/badge-examples.js
index e8c9f78a47489a268ceaf844f399ed1d7c0ef5bd..3b7cca205d08458d2ee5ac584db2e50e98d1a61c 100644
--- a/frontend/components/badge-examples.js
+++ b/frontend/components/badge-examples.js
@@ -1,8 +1,8 @@
-import React from 'react';
-import { Link } from "react-router-dom";
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import resolveBadgeUrl from '../lib/badge-url';
+import React from 'react'
+import { Link } from 'react-router-dom'
+import PropTypes from 'prop-types'
+import classNames from 'classnames'
+import resolveBadgeUrl from '../lib/badge-url'
 
 const Badge = ({
   title,
@@ -14,39 +14,49 @@ const Badge = ({
   shouldDisplay = () => true,
   onClick,
 }) => {
-  const handleClick = onClick ?
-    () => onClick({ title, previewUri, exampleUri, documentation })
-    : undefined;
+  const handleClick = onClick
+    ? () => onClick({ title, previewUri, exampleUri, documentation })
+    : undefined
 
-  const previewImage = previewUri
-    ? (<img
+  const previewImage = previewUri ? (
+    <img
       className={classNames('badge-img', { clickable: onClick })}
       onClick={handleClick}
-      src={resolveBadgeUrl(previewUri, baseUri, { longCache } )}
-      alt="" />
-    ) : '\u00a0'; // non-breaking space
+      src={resolveBadgeUrl(previewUri, baseUri, { longCache })}
+      alt=""
+    />
+  ) : (
+    '\u00a0'
+  ) // non-breaking space
   const resolvedExampleUri = resolveBadgeUrl(
     exampleUri || previewUri,
     baseUri,
-    { longCache: false });
+    { longCache: false }
+  )
 
   if (shouldDisplay()) {
     return (
       <tr>
-        <th className={classNames({ clickable: onClick })} onClick={handleClick}>
-          { title }:
+        <th
+          className={classNames({ clickable: onClick })}
+          onClick={handleClick}
+        >
+          {title}:
         </th>
-        <td>{ previewImage }</td>
+        <td>{previewImage}</td>
         <td>
-          <code className={classNames({ clickable: onClick })} onClick={handleClick}>
-            { resolvedExampleUri }
+          <code
+            className={classNames({ clickable: onClick })}
+            onClick={handleClick}
+          >
+            {resolvedExampleUri}
           </code>
         </td>
       </tr>
-    );
+    )
   }
-  return null;
-};
+  return null
+}
 Badge.propTypes = {
   title: PropTypes.string.isRequired,
   previewUri: PropTypes.string,
@@ -56,75 +66,74 @@ Badge.propTypes = {
   longCache: PropTypes.bool.isRequired,
   shouldDisplay: PropTypes.func,
   onClick: PropTypes.func.isRequired,
-};
+}
 
 const Category = ({ category, examples, baseUri, longCache, onClick }) => {
-  if (examples.filter(example => example.shouldDisplay()).length === 0){
-    return null;
+  if (examples.filter(example => example.shouldDisplay()).length === 0) {
+    return null
   }
   return (
     <div>
       <Link to={'/examples/' + category.id}>
-        <h3 id={category.id}>{ category.name }</h3>
+        <h3 id={category.id}>{category.name}</h3>
       </Link>
       <table className="badge">
         <tbody>
-          {
-            examples.map(badgeData => (
-              <Badge
-                key={badgeData.key}
-                {...badgeData}
-                baseUri={baseUri}
-                longCache={longCache}
-                onClick={onClick} />
-            ))
-          }
+          {examples.map(badgeData => (
+            <Badge
+              key={badgeData.key}
+              {...badgeData}
+              baseUri={baseUri}
+              longCache={longCache}
+              onClick={onClick}
+            />
+          ))}
         </tbody>
       </table>
     </div>
-  );
-};
+  )
+}
 Category.propTypes = {
   category: PropTypes.shape({
     id: PropTypes.string.isRequired,
     name: PropTypes.string.isRequired,
   }).isRequired,
-  examples: PropTypes.arrayOf(PropTypes.shape({
-    title: PropTypes.string.isRequired,
-    previewUri: PropTypes.string,
-    exampleUri: PropTypes.string,
-    documentation: PropTypes.string,
-  })).isRequired,
+  examples: PropTypes.arrayOf(
+    PropTypes.shape({
+      title: PropTypes.string.isRequired,
+      previewUri: PropTypes.string,
+      exampleUri: PropTypes.string,
+      documentation: PropTypes.string,
+    })
+  ).isRequired,
   baseUri: PropTypes.string,
   longCache: PropTypes.bool.isRequired,
   onClick: PropTypes.func.isRequired,
-};
+}
 
 const BadgeExamples = ({ categories, baseUri, longCache, onClick }) => (
   <div>
-    {
-      categories.map((categoryData, i) => (
-        <Category
-          key={i}
-          {...categoryData}
-          baseUri={baseUri}
-          longCache={longCache}
-          onClick={onClick} />
-      ))
-    }
+    {categories.map((categoryData, i) => (
+      <Category
+        key={i}
+        {...categoryData}
+        baseUri={baseUri}
+        longCache={longCache}
+        onClick={onClick}
+      />
+    ))}
   </div>
-);
+)
 BadgeExamples.propTypes = {
-  categories: PropTypes.arrayOf(PropTypes.shape({
-    category: Category.propTypes.category,
-    examples: Category.propTypes.examples,
-  })),
+  categories: PropTypes.arrayOf(
+    PropTypes.shape({
+      category: Category.propTypes.category,
+      examples: Category.propTypes.examples,
+    })
+  ),
   baseUri: PropTypes.string,
   longCache: PropTypes.bool.isRequired,
   onClick: PropTypes.func.isRequired,
-};
+}
 
-export {
-  Badge,
-  BadgeExamples,
-};
+export { Badge, BadgeExamples }
diff --git a/frontend/components/dynamic-badge-maker.js b/frontend/components/dynamic-badge-maker.js
index e6ac8a6bee8cc4c5c249e36bc75f2c3a0735945a..a8eb0f1957ac37d0666bf8ca6216c5190991ca1c 100644
--- a/frontend/components/dynamic-badge-maker.js
+++ b/frontend/components/dynamic-badge-maker.js
@@ -1,11 +1,11 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { dynamicBadgeUrl } from '../lib/badge-url';
+import React from 'react'
+import PropTypes from 'prop-types'
+import { dynamicBadgeUrl } from '../lib/badge-url'
 
 export default class DynamicBadgeMaker extends React.Component {
   static propTypes = {
     baseUri: PropTypes.string,
-  };
+  }
 
   state = {
     datatype: '',
@@ -15,22 +15,26 @@ export default class DynamicBadgeMaker extends React.Component {
     color: '',
     prefix: '',
     suffix: '',
-  };
+  }
 
-  makeBadgeUri () {
-    const { datatype, label, url, query, color, prefix, suffix } = this.state;
-    const { baseUri: baseUrl = document.location.href } = this.props;
-    return dynamicBadgeUrl(baseUrl, datatype, label, url, query, { color, prefix, suffix });
+  makeBadgeUri() {
+    const { datatype, label, url, query, color, prefix, suffix } = this.state
+    const { baseUri: baseUrl = document.location.href } = this.props
+    return dynamicBadgeUrl(baseUrl, datatype, label, url, query, {
+      color,
+      prefix,
+      suffix,
+    })
   }
 
   handleSubmit(e) {
-    e.preventDefault();
-    document.location = this.makeBadgeUri();
+    e.preventDefault()
+    document.location = this.makeBadgeUri()
   }
 
   get isValid() {
-    const { datatype, label, url, query } = this.state;
-    return datatype && label && url && query;
+    const { datatype, label, url, query } = this.state
+    return datatype && label && url && query
   }
 
   render() {
@@ -39,44 +43,60 @@ export default class DynamicBadgeMaker extends React.Component {
         <select
           className="short"
           value={this.state.datatype}
-          onChange={event => this.setState({ datatype: event.target.value })}>
-          <option value="" disabled>data type</option>
+          onChange={event => this.setState({ datatype: event.target.value })}
+        >
+          <option value="" disabled>
+            data type
+          </option>
           <option value="json">json</option>
           <option value="xml">xml</option>
           <option value="yaml">yaml</option>
-        </select> {}
+        </select>{' '}
+        {}
         <input
           className="short"
           value={this.state.label}
           onChange={event => this.setState({ label: event.target.value })}
-          placeholder="label" /> {}
+          placeholder="label"
+        />{' '}
+        {}
         <input
           className="short"
           value={this.state.url}
           onChange={event => this.setState({ url: event.target.value })}
-          placeholder="url" /> {}
+          placeholder="url"
+        />{' '}
+        {}
         <input
           className="short"
           value={this.state.query}
           onChange={event => this.setState({ query: event.target.value })}
-          placeholder="query" /> {}
+          placeholder="query"
+        />{' '}
+        {}
         <input
           className="short"
           value={this.state.color}
           onChange={event => this.setState({ color: event.target.value })}
-          placeholder="color" /> {}
+          placeholder="color"
+        />{' '}
+        {}
         <input
           className="short"
           value={this.state.prefix}
           onChange={event => this.setState({ prefix: event.target.value })}
-          placeholder="prefix" /> {}
+          placeholder="prefix"
+        />{' '}
+        {}
         <input
           className="short"
           value={this.state.suffix}
           onChange={event => this.setState({ suffix: event.target.value })}
-          placeholder="suffix" /> {}
-        <button disabled={! this.isValid}>Make Badge</button>
+          placeholder="suffix"
+        />{' '}
+        {}
+        <button disabled={!this.isValid}>Make Badge</button>
       </form>
-    );
+    )
   }
 }
diff --git a/frontend/components/examples-page.js b/frontend/components/examples-page.js
index 6a41794db2030be99d1ac07071a795b6c2307704..f60b512e612f8227123072d9033271add2bf88e5 100644
--- a/frontend/components/examples-page.js
+++ b/frontend/components/examples-page.js
@@ -1,27 +1,26 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import Meta from './meta';
-import Header from './header';
-import SuggestionAndSearch from './suggestion-and-search';
-import SearchResults from './search-results';
-import MarkupModal from './markup-modal';
-import Usage from './usage';
-import Footer from './footer';
-import { baseUri, longCache } from '../constants';
+import React from 'react'
+import PropTypes from 'prop-types'
+import Meta from './meta'
+import Header from './header'
+import SuggestionAndSearch from './suggestion-and-search'
+import SearchResults from './search-results'
+import MarkupModal from './markup-modal'
+import Usage from './usage'
+import Footer from './footer'
+import { baseUri, longCache } from '../constants'
 
 export default class ExamplesPage extends React.Component {
-
   constructor(props) {
-    super(props);
+    super(props)
     this.state = {
       category: props.match.params.id,
       query: null,
       example: null,
       searchReady: true,
-    };
-    this.searchTimeout = 0;
-    this.renderSearchResults = this.renderSearchResults.bind(this);
-    this.searchQueryChanged = this.searchQueryChanged.bind(this);
+    }
+    this.searchTimeout = 0
+    this.renderSearchResults = this.renderSearchResults.bind(this)
+    this.searchQueryChanged = this.searchQueryChanged.bind(this)
   }
 
   static propTypes = {
@@ -29,7 +28,7 @@ export default class ExamplesPage extends React.Component {
   }
 
   searchQueryChanged(query) {
-    this.setState({searchReady: false});
+    this.setState({ searchReady: false })
     /*
     Add a small delay before showing search results
     so that we wait until the user has stipped typing
@@ -40,29 +39,32 @@ export default class ExamplesPage extends React.Component {
     b) stops the page from 'flashing' as the user types, like this:
     https://user-images.githubusercontent.com/7288322/42600206-9b278470-85b5-11e8-9f63-eb4a0c31cb4a.gif
     */
-    window.clearTimeout(this.searchTimeout);
+    window.clearTimeout(this.searchTimeout)
     this.searchTimeout = window.setTimeout(() => {
       this.setState({
         searchReady: true,
-        query: query
-      });
-    }, 500);
+        query: query,
+      })
+    }, 500)
   }
 
   renderSearchResults() {
     if (this.state.searchReady) {
-      if ((this.state.query != null) && (this.state.query.length === 1)) {
-        return (<div>Search term must have 2 or more characters</div>);
+      if (this.state.query != null && this.state.query.length === 1) {
+        return <div>Search term must have 2 or more characters</div>
       } else {
         return (
           <SearchResults
             category={this.state.category}
             query={this.state.query}
-            clickHandler={example => { this.setState({ example }); }} />
-        );
+            clickHandler={example => {
+              this.setState({ example })
+            }}
+          />
+        )
       }
     } else {
-      return (<div>searching...</div>);
+      return <div>searching...</div>
     }
   }
 
@@ -73,32 +75,34 @@ export default class ExamplesPage extends React.Component {
         <Header />
         <MarkupModal
           example={this.state.example}
-          onRequestClose={() => { this.setState({ example: null }); }}
-          baseUri={baseUri} />
+          onRequestClose={() => {
+            this.setState({ example: null })
+          }}
+          baseUri={baseUri}
+        />
         <section>
           <SuggestionAndSearch
             queryChanged={this.searchQueryChanged}
-            onBadgeClick={example => { this.setState({ example }); }}
+            onBadgeClick={example => {
+              this.setState({ example })
+            }}
             baseUri={baseUri}
-            longCache={longCache} />
-          <a
-            className="donate"
-            href="https://opencollective.com/shields">
+            longCache={longCache}
+          />
+          <a className="donate" href="https://opencollective.com/shields">
             donate
           </a>
         </section>
-        { this.renderSearchResults() }
-        <Usage
-          baseUri={baseUri}
-          longCache={longCache} />
+        {this.renderSearchResults()}
+        <Usage baseUri={baseUri} longCache={longCache} />
         <Footer baseUri={baseUri} />
         <style jsx>{`
           .donate {
             text-decoration: none;
-            color: rgba(0,0,0,0.1);
+            color: rgba(0, 0, 0, 0.1);
           }
         `}</style>
       </div>
-    );
+    )
   }
 }
diff --git a/frontend/components/footer.js b/frontend/components/footer.js
index 71ed716e19e663a2a336a955f280ee1f8d4602c2..f7ae023690c43c7299ef44da5573d6ad97f1af4a 100644
--- a/frontend/components/footer.js
+++ b/frontend/components/footer.js
@@ -1,41 +1,63 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import resolveUrl from '../lib/resolve-url';
+import React from 'react'
+import PropTypes from 'prop-types'
+import resolveUrl from '../lib/resolve-url'
 
 const Footer = ({ baseUri }) => (
   <section>
     <h2 id="like-this">Like This?</h2>
 
     <p>
-      What is your favorite badge service to use?<br />
-      <a href="https://github.com/badges/shields/blob/master/CONTRIBUTING.md">Tell us</a> and we might bring it to you!
+      What is your favorite badge service to use?
+      <br />
+      <a href="https://github.com/badges/shields/blob/master/CONTRIBUTING.md">
+        Tell us
+      </a>{' '}
+      and we might bring it to you!
     </p>
     <p>
       <object
-        data={resolveUrl('/twitter/follow/shields_io.svg?style=social&label=Follow', baseUri)}
-        alt="Follow @shields_io" /> {}
+        data={resolveUrl(
+          '/twitter/follow/shields_io.svg?style=social&label=Follow',
+          baseUri
+        )}
+        alt="Follow @shields_io"
+      />{' '}
+      {}
       <a href="https://opencollective.com/shields" alt="Donate to us!">
         <img src="https://opencollective.com/shields/backers/badge.svg?style=social" />
-      </a> {}
+      </a>{' '}
+      {}
       <a href="https://opencollective.com/shields" alt="Donate to us!">
         <img src="https://opencollective.com/shields/sponsors/badge.svg?style=social" />
-      </a> {}
+      </a>{' '}
+      {}
       <object
-        data={resolveUrl('/github/forks/badges/shields.svg?style=social&label=Fork', baseUri)}
-        alt="Fork on GitHub" /> {}
+        data={resolveUrl(
+          '/github/forks/badges/shields.svg?style=social&label=Fork',
+          baseUri
+        )}
+        alt="Fork on GitHub"
+      />{' '}
+      {}
       <object
-        data={resolveUrl('/discord/308323056592486420.svg?style=social&label=Chat&link=https://discord.gg/HjJCwm5', baseUri)}
-        alt="chat on Discord" />
+        data={resolveUrl(
+          '/discord/308323056592486420.svg?style=social&label=Chat&link=https://discord.gg/HjJCwm5',
+          baseUri
+        )}
+        alt="chat on Discord"
+      />
     </p>
     <p>
       <a href="https://github.com/h5bp/lazyweb-requests/issues/150">This</a> is
       where the current server got started.
     </p>
 
-    <p><small>:wq</small></p>
+    <p>
+      <small>:wq</small>
+    </p>
   </section>
-);
-export default Footer;
+)
+export default Footer
 Footer.propTypes = {
   baseUri: PropTypes.string.isRequired,
-};
+}
diff --git a/frontend/components/header.js b/frontend/components/header.js
index 83a59e40231a648162207fee4af90a5ca3212e82..2cbe19a71b65c494ce76dbe691706e7c7f9a05c8 100644
--- a/frontend/components/header.js
+++ b/frontend/components/header.js
@@ -1,5 +1,5 @@
-import { Link } from "react-router-dom";
-import React from 'react';
+import { Link } from 'react-router-dom'
+import React from 'react'
 
 export default () => (
   <section>
@@ -10,12 +10,8 @@ export default () => (
     <hr className="spacing" />
 
     <p className="highlights">
-      Pixel-perfect &nbsp;
-      Retina-ready &nbsp;
-      Fast &nbsp;
-      Consistent &nbsp;
-      Hackable &nbsp;
-      No tracking
+      Pixel-perfect &nbsp; Retina-ready &nbsp; Fast &nbsp; Consistent &nbsp;
+      Hackable &nbsp; No tracking
     </p>
 
     <style jsx>{`
@@ -24,4 +20,4 @@ export default () => (
       }
     `}</style>
   </section>
-);
+)
diff --git a/frontend/components/markup-modal.js b/frontend/components/markup-modal.js
index 93cca54bbb20c5349453c1fda912f543ca07b9cb..1e7231e73fdcfb08d2a987f7acd3f64d226b3563 100644
--- a/frontend/components/markup-modal.js
+++ b/frontend/components/markup-modal.js
@@ -1,10 +1,10 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import Modal from 'react-modal';
-import ClickToSelect from '@mapbox/react-click-to-select';
-import resolveBadgeUrl from '../lib/badge-url';
-import generateAllMarkup from '../lib/generate-image-markup';
-import { advertisedStyles } from '../../supported-features.json';
+import React from 'react'
+import PropTypes from 'prop-types'
+import Modal from 'react-modal'
+import ClickToSelect from '@mapbox/react-click-to-select'
+import resolveBadgeUrl from '../lib/badge-url'
+import generateAllMarkup from '../lib/generate-image-markup'
+import { advertisedStyles } from '../../supported-features.json'
 
 export default class MarkupModal extends React.Component {
   static propTypes = {
@@ -17,80 +17,87 @@ export default class MarkupModal extends React.Component {
     }),
     baseUri: PropTypes.string.isRequired,
     onRequestClose: PropTypes.func.isRequired,
-  };
+  }
 
   state = {
     badgeUri: null,
     link: null,
     style: 'flat',
-  };
+  }
 
   get isOpen() {
-    return this.props.example !== null;
+    return this.props.example !== null
   }
 
   componentWillReceiveProps(nextProps) {
-    const { example, baseUri } = nextProps;
+    const { example, baseUri } = nextProps
 
-    if (! example) {
-      return;
+    if (!example) {
+      return
     }
 
     // Transfer `badgeUri` and `link` into state so they can be edited by the
     // user.
-    const { exampleUri, previewUri, link } = example;
+    const { exampleUri, previewUri, link } = example
     this.setState({
-      badgeUri: resolveBadgeUrl(exampleUri || previewUri, baseUri || window.location.href),
+      badgeUri: resolveBadgeUrl(
+        exampleUri || previewUri,
+        baseUri || window.location.href
+      ),
       link,
-    });
+    })
   }
 
   generateCompleteBadgeUrl() {
-    const { baseUri } = this.props;
-    const { badgeUri, style } = this.state;
+    const { baseUri } = this.props
+    const { badgeUri, style } = this.state
 
     return resolveBadgeUrl(
       badgeUri,
       baseUri || window.location.href,
       // Default style doesn't need to be specified.
-      style === 'flat' ? undefined : { style });
+      style === 'flat' ? undefined : { style }
+    )
   }
 
   generateMarkup() {
-    if (! this.isOpen) {
-      return {};
+    if (!this.isOpen) {
+      return {}
     }
 
-    const { title } = this.props.example;
-    const { link } = this.state;
-    const completeBadgeUrl = this.generateCompleteBadgeUrl();
-    return generateAllMarkup(completeBadgeUrl, link, title);
+    const { title } = this.props.example
+    const { link } = this.state
+    const completeBadgeUrl = this.generateCompleteBadgeUrl()
+    return generateAllMarkup(completeBadgeUrl, link, title)
   }
 
   renderDocumentation() {
-    if (! this.isOpen) {
-      return null;
+    if (!this.isOpen) {
+      return null
     }
 
-    const { documentation } = this.props.example;
+    const { documentation } = this.props.example
     return documentation ? (
       <div>
         <h4>Documentation</h4>
         <div dangerouslySetInnerHTML={{ __html: documentation }} />
       </div>
-    ) : null;
+    ) : null
   }
 
   render() {
-    const { markdown, reStructuredText, asciiDoc } = this.generateMarkup();
+    const { markdown, reStructuredText, asciiDoc } = this.generateMarkup()
 
-    const completeBadgeUrl = this.isOpen ? this.generateCompleteBadgeUrl() : undefined;
+    const completeBadgeUrl = this.isOpen
+      ? this.generateCompleteBadgeUrl()
+      : undefined
 
     return (
       <Modal
         isOpen={this.isOpen}
         onRequestClose={this.props.onRequestClose}
-        contentLabel="Example Modal">
+        contentLabel="Example Modal"
+      >
         <form action="">
           <p>
             <img className="badge-img" src={completeBadgeUrl} />
@@ -101,7 +108,10 @@ export default class MarkupModal extends React.Component {
               <input
                 type="url"
                 value={this.state.link}
-                onChange={event => { this.setState({ link: event.target.value }); }} />
+                onChange={event => {
+                  this.setState({ link: event.target.value })
+                }}
+              />
             </label>
           </p>
           <p>
@@ -110,7 +120,10 @@ export default class MarkupModal extends React.Component {
               <input
                 type="url"
                 value={this.state.badgeUri}
-                onChange={event => { this.setState({ badgeUri: event.target.value }); }} />
+                onChange={event => {
+                  this.setState({ badgeUri: event.target.value })
+                }}
+              />
             </label>
           </p>
           <p>
@@ -118,12 +131,15 @@ export default class MarkupModal extends React.Component {
               Style&nbsp;
               <select
                 value={this.state.style}
-                onChange={event => { this.setState({ style: event.target.value }); }}>
-                {
-                  advertisedStyles.map(style => (
-                    <option key={style} value={style}>{style}</option>
-                  ))
-                }
+                onChange={event => {
+                  this.setState({ style: event.target.value })
+                }}
+              >
+                {advertisedStyles.map(style => (
+                  <option key={style} value={style}>
+                    {style}
+                  </option>
+                ))}
               </select>
             </label>
           </p>
@@ -136,7 +152,11 @@ export default class MarkupModal extends React.Component {
           <p>
             reStructuredText&nbsp;
             <ClickToSelect>
-              <input className="code clickable" readOnly value={reStructuredText} />
+              <input
+                className="code clickable"
+                readOnly
+                value={reStructuredText}
+              />
             </ClickToSelect>
           </p>
           <p>
@@ -145,11 +165,9 @@ export default class MarkupModal extends React.Component {
               <input className="code clickable" readOnly value={asciiDoc} />
             </ClickToSelect>
           </p>
-          {
-            this.renderDocumentation()
-          }
+          {this.renderDocumentation()}
         </form>
       </Modal>
-    );
+    )
   }
 }
diff --git a/frontend/components/meta.js b/frontend/components/meta.js
index ffe4624c83593a00f4d78485b1286851e81d6d19..840ead75e179a26780e718a8d534949bb946c27e 100644
--- a/frontend/components/meta.js
+++ b/frontend/components/meta.js
@@ -1,9 +1,9 @@
-import React from 'react';
-import Head from 'next/head';
+import React from 'react'
+import Head from 'next/head'
 
 const description = `We serve fast and scalable informational images as badges
 for GitHub, Travis CI, Jenkins, WordPress and many more services. Use them to
-track the state of your projects, or for promotional purposes.`;
+track the state of your projects, or for promotional purposes.`
 
 export default () => (
   <Head>
@@ -13,6 +13,9 @@ export default () => (
     <meta name="description" content={description} />
     <link rel="icon" type="image/png" href="favicon.png" />
     <link href="/static/main.css" rel="stylesheet" />
-    <link href="https://fonts.googleapis.com/css?family=Lekton" rel="stylesheet" />
+    <link
+      href="https://fonts.googleapis.com/css?family=Lekton"
+      rel="stylesheet"
+    />
   </Head>
-);
+)
diff --git a/frontend/components/search-results.js b/frontend/components/search-results.js
index c39cabddf4944d95595dd397036bad9d04e6e226..5343f39659c35c835908642f37b8ffdba19537a1 100644
--- a/frontend/components/search-results.js
+++ b/frontend/components/search-results.js
@@ -1,14 +1,12 @@
-import React from 'react';
-import { Link } from "react-router-dom";
-import PropTypes from 'prop-types';
-import { BadgeExamples } from './badge-examples';
-import badgeExampleData from '../../badge-examples.json';
-import { prepareExamples, predicateFromQuery } from '../lib/prepare-examples';
-import { baseUri, longCache } from '../constants';
-
+import React from 'react'
+import { Link } from 'react-router-dom'
+import PropTypes from 'prop-types'
+import { BadgeExamples } from './badge-examples'
+import badgeExampleData from '../../badge-examples.json'
+import { prepareExamples, predicateFromQuery } from '../lib/prepare-examples'
+import { baseUri, longCache } from '../constants'
 
 export default class SearchResults extends React.Component {
-
   static propTypes = {
     category: PropTypes.string,
     query: PropTypes.string,
@@ -16,8 +14,10 @@ export default class SearchResults extends React.Component {
   }
 
   prepareExamples(category) {
-    const examples = category ? badgeExampleData.filter(example => example.category.id === category) : badgeExampleData;
-    return prepareExamples(examples, () => predicateFromQuery(this.props.query));
+    const examples = category
+      ? badgeExampleData.filter(example => example.category.id === category)
+      : badgeExampleData
+    return prepareExamples(examples, () => predicateFromQuery(this.props.query))
   }
 
   renderExamples() {
@@ -26,31 +26,33 @@ export default class SearchResults extends React.Component {
         categories={this.preparedExamples}
         onClick={this.props.clickHandler}
         baseUri={baseUri}
-        longCache={longCache} />
-    );
+        longCache={longCache}
+      />
+    )
   }
 
   renderCategoryHeadings() {
     return this.preparedExamples.map(function(category, i) {
       return (
-        <Link to={'/examples/' + category.category.id} key={category.category.id}>
-          <h3 id={category.category.id}>{ category.category.name }</h3>
+        <Link
+          to={'/examples/' + category.category.id}
+          key={category.category.id}
+        >
+          <h3 id={category.category.id}>{category.category.name}</h3>
         </Link>
       )
-    });
+    })
   }
 
   render() {
-    this.preparedExamples = this.prepareExamples(this.props.category);
+    this.preparedExamples = this.prepareExamples(this.props.category)
 
     if (this.props.category) {
-      return this.renderExamples();
-    } else if ((this.props.query == null) || (this.props.query.length === 0)) {
-      return this.renderCategoryHeadings();
+      return this.renderExamples()
+    } else if (this.props.query == null || this.props.query.length === 0) {
+      return this.renderCategoryHeadings()
     } else {
-      return this.renderExamples();
+      return this.renderExamples()
     }
-
   }
-
 }
diff --git a/frontend/components/static-badge-maker.js b/frontend/components/static-badge-maker.js
index 1ae584a684541aec925f841db2ef50520031e1dc..0c8b8c73c7f760be5d560623cb6ba2e03edb7f1b 100644
--- a/frontend/components/static-badge-maker.js
+++ b/frontend/components/static-badge-maker.js
@@ -1,26 +1,31 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { staticBadgeUrl } from '../lib/badge-url';
+import React from 'react'
+import PropTypes from 'prop-types'
+import { staticBadgeUrl } from '../lib/badge-url'
 
 export default class StaticBadgeMaker extends React.Component {
   static propTypes = {
     baseUri: PropTypes.string,
-  };
+  }
 
   state = {
     subject: '',
     status: '',
     color: '',
-  };
+  }
 
-  handleSubmit (e) {
-    e.preventDefault();
+  handleSubmit(e) {
+    e.preventDefault()
 
-    const { baseUri } = this.props;
-    const { subject, status, color } = this.state;
-    const badgeUri = staticBadgeUrl(baseUri || window.location.href, subject, status, color);
+    const { baseUri } = this.props
+    const { subject, status, color } = this.state
+    const badgeUri = staticBadgeUrl(
+      baseUri || window.location.href,
+      subject,
+      status,
+      color
+    )
 
-    document.location = badgeUri;
+    document.location = badgeUri
   }
 
   render() {
@@ -30,18 +35,24 @@ export default class StaticBadgeMaker extends React.Component {
           className="short"
           value={this.state.subject}
           onChange={event => this.setState({ subject: event.target.value })}
-          placeholder="subject" /> {}
+          placeholder="subject"
+        />{' '}
+        {}
         <input
           className="short"
           value={this.state.status}
           onChange={event => this.setState({ status: event.target.value })}
-          placeholder="status" /> {}
+          placeholder="status"
+        />{' '}
+        {}
         <input
           className="short"
           value={this.state.color}
           onChange={event => this.setState({ color: event.target.value })}
           list="default-colors"
-          placeholder="color" /> {}
+          placeholder="color"
+        />{' '}
+        {}
         <datalist id="default-colors">
           <option value="brightgreen" />
           <option value="green" />
@@ -51,9 +62,10 @@ export default class StaticBadgeMaker extends React.Component {
           <option value="red" />
           <option value="lightgrey" />
           <option value="blue" />
-        </datalist> {}
+        </datalist>{' '}
+        {}
         <button>Make Badge</button>
       </form>
-    );
+    )
   }
 }
diff --git a/frontend/components/suggestion-and-search.js b/frontend/components/suggestion-and-search.js
index 5c73f707de19e5e221e03de2aca6e858a681ffbd..2a1c30016cb868db33b1dddada62baeb230e9849 100644
--- a/frontend/components/suggestion-and-search.js
+++ b/frontend/components/suggestion-and-search.js
@@ -1,9 +1,9 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import fetchPonyfill from 'fetch-ponyfill';
-import debounce from 'lodash.debounce';
-import { Badge } from './badge-examples';
-import resolveUrl from '../lib/resolve-url';
+import React from 'react'
+import PropTypes from 'prop-types'
+import fetchPonyfill from 'fetch-ponyfill'
+import debounce from 'lodash.debounce'
+import { Badge } from './badge-examples'
+import resolveUrl from '../lib/resolve-url'
 
 export default class SuggestionAndSearch extends React.Component {
   static propTypes = {
@@ -11,11 +11,13 @@ export default class SuggestionAndSearch extends React.Component {
     onBadgeClick: PropTypes.func.isRequired,
     baseUri: PropTypes.string.isRequired,
     longCache: PropTypes.bool.isRequired,
-  };
+  }
 
   constructor(props) {
-    super(props);
-    this.queryChangedDebounced = debounce(props.queryChanged, 50, { leading: true });
+    super(props)
+    this.queryChangedDebounced = debounce(props.queryChanged, 50, {
+      leading: true,
+    })
   }
 
   state = {
@@ -23,63 +25,68 @@ export default class SuggestionAndSearch extends React.Component {
     inProgress: false,
     projectUrl: null,
     suggestions: [],
-  };
+  }
 
   queryChanged(query) {
-    const isUri = query.startsWith('https://') || query.startsWith('http://');
+    const isUri = query.startsWith('https://') || query.startsWith('http://')
     this.setState({
       isUri,
       projectUri: isUri ? query : null,
-    });
+    })
 
-    this.queryChangedDebounced(query);
+    this.queryChangedDebounced(query)
   }
 
   getSuggestions() {
     this.setState({ inProgress: true }, () => {
-      const { baseUri } = this.props;
-      const { projectUri } = this.state;
+      const { baseUri } = this.props
+      const { projectUri } = this.state
 
-      const url = resolveUrl('/$suggest/v1', baseUri, { url: projectUri });
+      const url = resolveUrl('/$suggest/v1', baseUri, { url: projectUri })
 
-      const fetch = window.fetch || fetchPonyfill;
+      const fetch = window.fetch || fetchPonyfill
       fetch(url)
         .then(res => res.json())
         .then(json => {
-          this.setState({ inProgress: false, suggestions: json.badges });
+          this.setState({ inProgress: false, suggestions: json.badges })
         })
         .catch(() => {
-          this.setState({ inProgress: false, suggestions: [] });
-        });
-    });
+          this.setState({ inProgress: false, suggestions: [] })
+        })
+    })
   }
 
   renderSuggestions() {
-    const { baseUri, longCache } = this.props;
-    const { suggestions } = this.state;
+    const { baseUri, longCache } = this.props
+    const { suggestions } = this.state
 
     if (suggestions.length === 0) {
-      return null;
+      return null
     }
 
     return (
-      <table className="badge"><tbody>
-        { suggestions.map(({ name, link, badge }, i) => (
-          // TODO We need to deal with `link`.
-          <Badge
-            key={i}
-            title={name}
-            previewUri={badge}
-            onClick={() => this.props.onBadgeClick({
-              title: name,
-              previewUri: badge,
-              link,
-            })}
-            baseUri={baseUri}
-            longCache={longCache} />
-        ))}
-      </tbody></table>
-    );
+      <table className="badge">
+        <tbody>
+          {suggestions.map(({ name, link, badge }, i) => (
+            // TODO We need to deal with `link`.
+            <Badge
+              key={i}
+              title={name}
+              previewUri={badge}
+              onClick={() =>
+                this.props.onBadgeClick({
+                  title: name,
+                  previewUri: badge,
+                  link,
+                })
+              }
+              baseUri={baseUri}
+              longCache={longCache}
+            />
+          ))}
+        </tbody>
+      </table>
+    )
   }
 
   render() {
@@ -88,18 +95,21 @@ export default class SuggestionAndSearch extends React.Component {
         <form action="javascript:void 0" autoComplete="off">
           <input
             onChange={event => this.queryChanged(event.target.value)}
-            autofill="off" autoFocus
-            placeholder="search / project URL" />
+            autofill="off"
+            autoFocus
+            placeholder="search / project URL"
+          />
           <br />
           <button
             onClick={event => this.getSuggestions(event.target.value)}
             disabled={this.state.inProgress}
-            hidden={! this.state.isUri}>
+            hidden={!this.state.isUri}
+          >
             Suggest badges
           </button>
         </form>
-        { this.renderSuggestions() }
+        {this.renderSuggestions()}
       </section>
-    );
+    )
   }
 }
diff --git a/frontend/components/usage.js b/frontend/components/usage.js
index f61a57f8ba5ea6f58a5bcdf6d01fe1381720c0ee..547409e32796b30d5900fd9f4a772fffd8f7f783 100644
--- a/frontend/components/usage.js
+++ b/frontend/components/usage.js
@@ -1,18 +1,18 @@
-import { Fragment, default as React } from 'react';
-import PropTypes from 'prop-types';
-import StaticBadgeMaker from './static-badge-maker';
-import DynamicBadgeMaker from './dynamic-badge-maker';
-import { staticBadgeUrl } from '../lib/badge-url';
-import { advertisedStyles, logos } from '../../supported-features.json';
+import { Fragment, default as React } from 'react'
+import PropTypes from 'prop-types'
+import StaticBadgeMaker from './static-badge-maker'
+import DynamicBadgeMaker from './dynamic-badge-maker'
+import { staticBadgeUrl } from '../lib/badge-url'
+import { advertisedStyles, logos } from '../../supported-features.json'
 
 export default class Usage extends React.PureComponent {
   static propTypes = {
     baseUri: PropTypes.string.isRequired,
     longCache: PropTypes.bool.isRequired,
-  };
+  }
 
-  renderColorExamples () {
-    const { baseUri, longCache } = this.props;
+  renderColorExamples() {
+    const { baseUri, longCache } = this.props
     const colors = [
       'brightgreen',
       'green',
@@ -23,33 +23,35 @@ export default class Usage extends React.PureComponent {
       'lightgrey',
       'blue',
       'ff69b4',
-    ];
+    ]
     return (
       <p>
-        { colors.map((color, i) => (
+        {colors.map((color, i) => (
           <Fragment key={i}>
             <img
               className="badge-img"
-              src={staticBadgeUrl(baseUri, 'color', color, color, { longCache })}
-              alt={color} /> {}
+              src={staticBadgeUrl(baseUri, 'color', color, color, {
+                longCache,
+              })}
+              alt={color}
+            />{' '}
+            {}
           </Fragment>
         ))}
       </p>
-    );
+    )
   }
 
-  renderStyleExamples () {
-    const { baseUri, longCache } = this.props;
+  renderStyleExamples() {
+    const { baseUri, longCache } = this.props
     return (
       <table className="badge-img">
         <tbody>
-          { advertisedStyles.map((style, i) => {
-            const badgeUri = staticBadgeUrl(
-              baseUri,
-              'style',
+          {advertisedStyles.map((style, i) => {
+            const badgeUri = staticBadgeUrl(baseUri, 'style', style, 'green', {
+              longCache,
               style,
-              'green',
-              { longCache, style });
+            })
             return (
               <tr key={i}>
                 <td>
@@ -59,23 +61,23 @@ export default class Usage extends React.PureComponent {
                   <code>{badgeUri}</code>
                 </td>
               </tr>
-            );
+            )
           })}
         </tbody>
       </table>
-    );
+    )
   }
 
   static renderNamedLogos() {
-    const renderLogo = logo => <span className="nowrap">{logo}</span>;
-    const [first, ...rest] = logos;
+    const renderLogo = logo => <span className="nowrap">{logo}</span>
+    const [first, ...rest] = logos
     return [renderLogo(first)].concat(
       rest.reduce((result, logo) => result.concat([', ', renderLogo(logo)]), [])
-    );
+    )
   }
 
   render() {
-    const { baseUri } = this.props;
+    const { baseUri } = this.props
     return (
       <section>
         <h2 id="your-badge">Your Badge</h2>
@@ -87,7 +89,8 @@ export default class Usage extends React.PureComponent {
 
         <p>
           <code>
-            {baseUri}/badge/&lt;SUBJECT&gt;-&lt;STATUS&gt;-&lt;COLOR&gt;.svg
+            {baseUri}
+            /badge/&lt;SUBJECT&gt;-&lt;STATUS&gt;-&lt;COLOR&gt;.svg
           </code>
         </p>
         <table className="centered">
@@ -122,20 +125,50 @@ export default class Usage extends React.PureComponent {
           </tbody>
         </table>
 
-        { this.renderColorExamples() }
+        {this.renderColorExamples()}
 
         <h3 id="dynamic-badge">Dynamic</h3>
 
         <DynamicBadgeMaker baseUri={baseUri} />
 
         <p>
-          <code>/badge/dynamic/json.svg?url=&lt;URL&gt;&amp;label=&lt;LABEL&gt;&amp;query=&lt;<a href="https://www.npmjs.com/package/jsonpath" target="_BLANK" title="JSONdata syntax">$.DATA.SUBDATA</a>&gt;&amp;colorB=&lt;COLOR&gt;&amp;prefix=&lt;PREFIX&gt;&amp;suffix=&lt;SUFFIX&gt;</code>
+          <code>
+            /badge/dynamic/json.svg?url=&lt;URL&gt;&amp;label=&lt;LABEL&gt;&amp;query=&lt;
+            <a
+              href="https://www.npmjs.com/package/jsonpath"
+              target="_BLANK"
+              title="JSONdata syntax"
+            >
+              $.DATA.SUBDATA
+            </a>
+            &gt;&amp;colorB=&lt;COLOR&gt;&amp;prefix=&lt;PREFIX&gt;&amp;suffix=&lt;SUFFIX&gt;
+          </code>
         </p>
         <p>
-          <code>/badge/dynamic/xml.svg?url=&lt;URL&gt;&amp;label=&lt;LABEL&gt;&amp;query=&lt;<a href="https://www.npmjs.com/package/xpath" target="_BLANK" title="XPath syntax">//data/subdata</a>&gt;&amp;colorB=&lt;COLOR&gt;&amp;prefix=&lt;PREFIX&gt;&amp;suffix=&lt;SUFFIX&gt;</code>
+          <code>
+            /badge/dynamic/xml.svg?url=&lt;URL&gt;&amp;label=&lt;LABEL&gt;&amp;query=&lt;
+            <a
+              href="https://www.npmjs.com/package/xpath"
+              target="_BLANK"
+              title="XPath syntax"
+            >
+              //data/subdata
+            </a>
+            &gt;&amp;colorB=&lt;COLOR&gt;&amp;prefix=&lt;PREFIX&gt;&amp;suffix=&lt;SUFFIX&gt;
+          </code>
         </p>
         <p>
-          <code>/badge/dynamic/yaml.svg?url=&lt;URL&gt;&amp;label=&lt;LABEL&gt;&amp;query=&lt;<a href="https://www.npmjs.com/package/jsonpath" target="_BLANK" title="JSONdata syntax">$.DATA.SUBDATA</a>&gt;&amp;colorB=&lt;COLOR&gt;&amp;prefix=&lt;PREFIX&gt;&amp;suffix=&lt;SUFFIX&gt;</code>
+          <code>
+            /badge/dynamic/yaml.svg?url=&lt;URL&gt;&amp;label=&lt;LABEL&gt;&amp;query=&lt;
+            <a
+              href="https://www.npmjs.com/package/jsonpath"
+              target="_BLANK"
+              title="JSONdata syntax"
+            >
+              $.DATA.SUBDATA
+            </a>
+            &gt;&amp;colorB=&lt;COLOR&gt;&amp;prefix=&lt;PREFIX&gt;&amp;suffix=&lt;SUFFIX&gt;
+          </code>
         </p>
 
         <hr className="spacing" />
@@ -143,12 +176,14 @@ export default class Usage extends React.PureComponent {
         <h2 id="styles">Styles</h2>
 
         <p>
-          The following styles are available (flat is the default as of Feb 1st 2015):
+          The following styles are available (flat is the default as of Feb 1st
+          2015):
         </p>
-        { this.renderStyleExamples() }
+        {this.renderStyleExamples()}
 
         <p>
-          Here are a few other parameters you can use: (connecting several with "&" is possible)
+          Here are a few other parameters you can use: (connecting several with
+          "&" is possible)
         </p>
         <table className="usage">
           <tbody>
@@ -169,7 +204,11 @@ export default class Usage extends React.PureComponent {
                 <code>?logo=appveyor</code>
               </td>
               <td>
-                Insert one of the named logos from ({this.constructor.renderNamedLogos()}) or <a href="https://simpleicons.org/" target="_BLANK">simple-icons</a>
+                Insert one of the named logos from (
+                {this.constructor.renderNamedLogos()}) or{' '}
+                <a href="https://simpleicons.org/" target="_BLANK">
+                  simple-icons
+                </a>
               </td>
             </tr>
             <tr>
@@ -182,7 +221,10 @@ export default class Usage extends React.PureComponent {
               <td>
                 <code>?logoColor=violet</code>
               </td>
-              <td>Set the color of the logo (hex, rgb, rgba, hsl, hsla and css named colors supported)</td>
+              <td>
+                Set the color of the logo (hex, rgb, rgba, hsl, hsla and css
+                named colors supported)
+              </td>
             </tr>
             <tr>
               <td>
@@ -195,36 +237,45 @@ export default class Usage extends React.PureComponent {
                 <code>?link=http://left&amp;link=http://right</code>
               </td>
               <td>
-                Specify what clicking on the left/right of a badge should do (esp.
-                for social badge style)
+                Specify what clicking on the left/right of a badge should do
+                (esp. for social badge style)
               </td>
             </tr>
             <tr>
               <td>
                 <code>?colorA=abcdef</code>
               </td>
-              <td>Set background of the left part (hex, rgb, rgba, hsl, hsla and css named colors supported)</td>
+              <td>
+                Set background of the left part (hex, rgb, rgba, hsl, hsla and
+                css named colors supported)
+              </td>
             </tr>
             <tr>
               <td>
                 <code>?colorB=fedcba</code>
               </td>
-              <td>Set background of the right part (hex, rgb, rgba, hsl, hsla and css named colors supported)</td>
+              <td>
+                Set background of the right part (hex, rgb, rgba, hsl, hsla and
+                css named colors supported)
+              </td>
             </tr>
             <tr>
               <td>
                 <code>?maxAge=3600</code>
               </td>
-              <td>Set the HTTP cache lifetime in secs (values below the default (currently 120 seconds) will be ignored)</td>
+              <td>
+                Set the HTTP cache lifetime in secs (values below the default
+                (currently 120 seconds) will be ignored)
+              </td>
             </tr>
           </tbody>
         </table>
 
         <p>
-          We support <code>.svg</code>, <code>.json</code>, <code>.png</code> and a
-          few others, but use them responsibly.
+          We support <code>.svg</code>, <code>.json</code>, <code>.png</code>{' '}
+          and a few others, but use them responsibly.
         </p>
       </section>
-    );
+    )
   }
 }
diff --git a/frontend/constants.js b/frontend/constants.js
index 9e03a30f751bb638c50856e823b2cde4bb8fc4d1..007db9888e22678ec8560aab1d04cbdf32ab4319 100644
--- a/frontend/constants.js
+++ b/frontend/constants.js
@@ -1,9 +1,6 @@
-import envFlag from 'node-env-flag';
+import envFlag from 'node-env-flag'
 
-const baseUri = process.env.BASE_URL;
-const longCache = envFlag(process.env.LONG_CACHE, false);
+const baseUri = process.env.BASE_URL
+const longCache = envFlag(process.env.LONG_CACHE, false)
 
-export {
-  baseUri,
-  longCache
-}
+export { baseUri, longCache }
diff --git a/frontend/lib/badge-url.js b/frontend/lib/badge-url.js
index 6de3816118b5b51c51d5cdb521e7bb77768ca0ac..5280821c611688a919a16f688c2f023292c10cd8 100644
--- a/frontend/lib/badge-url.js
+++ b/frontend/lib/badge-url.js
@@ -1,47 +1,54 @@
-import resolveUrl from './resolve-url';
+import resolveUrl from './resolve-url'
 
 export default function resolveBadgeUrl(url, baseUrl, options) {
-  const { longCache, style, queryParams: inQueryParams } = options || {};
-  const outQueryParams = Object.assign({}, inQueryParams);
+  const { longCache, style, queryParams: inQueryParams } = options || {}
+  const outQueryParams = Object.assign({}, inQueryParams)
   if (longCache) {
-    outQueryParams.maxAge = '2592000';
+    outQueryParams.maxAge = '2592000'
   }
   if (style) {
-    outQueryParams.style = style;
+    outQueryParams.style = style
   }
-  return resolveUrl(url, baseUrl, outQueryParams);
+  return resolveUrl(url, baseUrl, outQueryParams)
 }
 
 export function encodeField(s) {
-  return encodeURIComponent(s.replace(/-/g, '--').replace(/_/g, '__'));
+  return encodeURIComponent(s.replace(/-/g, '--').replace(/_/g, '__'))
 }
 
 export function staticBadgeUrl(baseUrl, subject, status, color, options) {
-  const path = [subject, status, color].map(encodeField).join('-');
-  return resolveUrl(`/badge/${path}.svg`, baseUrl, options);
+  const path = [subject, status, color].map(encodeField).join('-')
+  return resolveUrl(`/badge/${path}.svg`, baseUrl, options)
 }
 
 // Options can include: { prefix, suffix, color, longCache, style, queryParams }
-export function dynamicBadgeUrl(baseUrl, datatype, label, dataUrl, query, options = {}) {
-  const { prefix, suffix, color, queryParams = {}, ...rest } = options;
+export function dynamicBadgeUrl(
+  baseUrl,
+  datatype,
+  label,
+  dataUrl,
+  query,
+  options = {}
+) {
+  const { prefix, suffix, color, queryParams = {}, ...rest } = options
 
   Object.assign(queryParams, {
     label,
     url: dataUrl,
     query,
-  });
+  })
 
   if (color) {
-    queryParams.colorB = color;
+    queryParams.colorB = color
   }
   if (prefix) {
-    queryParams.prefix = prefix;
+    queryParams.prefix = prefix
   }
   if (suffix) {
-    queryParams.suffix = suffix;
+    queryParams.suffix = suffix
   }
 
-  const outOptions = Object.assign({ queryParams }, rest);
+  const outOptions = Object.assign({ queryParams }, rest)
 
-  return resolveBadgeUrl(`/badge/dynamic/${datatype}.svg`, baseUrl, outOptions);
+  return resolveBadgeUrl(`/badge/dynamic/${datatype}.svg`, baseUrl, outOptions)
 }
diff --git a/frontend/lib/badge-url.spec.js b/frontend/lib/badge-url.spec.js
index 8d425354e2632eae0f2eb6a26b288378c5a720ed..f71dce3a6d97a524a07d65a07195e49cebca7275 100644
--- a/frontend/lib/badge-url.spec.js
+++ b/frontend/lib/badge-url.spec.js
@@ -1,61 +1,64 @@
-import { test, given } from 'sazerac';
+import { test, given } from 'sazerac'
 import {
   default as resolveBadgeUrl,
   encodeField,
   staticBadgeUrl,
   dynamicBadgeUrl,
-} from './badge-url';
+} from './badge-url'
 
 const resolveBadgeUrlWithLongCache = (url, baseUrl) =>
   resolveBadgeUrl(url, baseUrl, { longCache: true })
 
 describe('Badge URL functions', function() {
   test(resolveBadgeUrl, () => {
-    given('/badge/foo-bar-blue.svg', undefined)
-      .expect('/badge/foo-bar-blue.svg');
-    given('/badge/foo-bar-blue.svg', 'http://example.com')
-      .expect('http://example.com/badge/foo-bar-blue.svg');
-  });
+    given('/badge/foo-bar-blue.svg', undefined).expect(
+      '/badge/foo-bar-blue.svg'
+    )
+    given('/badge/foo-bar-blue.svg', 'http://example.com').expect(
+      'http://example.com/badge/foo-bar-blue.svg'
+    )
+  })
 
   test(resolveBadgeUrlWithLongCache, () => {
-    given('/badge/foo-bar-blue.svg', undefined)
-      .expect('/badge/foo-bar-blue.svg?maxAge=2592000');
-    given('/badge/foo-bar-blue.svg', 'http://example.com')
-      .expect('http://example.com/badge/foo-bar-blue.svg?maxAge=2592000');
+    given('/badge/foo-bar-blue.svg', undefined).expect(
+      '/badge/foo-bar-blue.svg?maxAge=2592000'
+    )
+    given('/badge/foo-bar-blue.svg', 'http://example.com').expect(
+      'http://example.com/badge/foo-bar-blue.svg?maxAge=2592000'
+    )
   })
 
   test(encodeField, () => {
-    given('foo').expect('foo');
-    given('').expect('');
-    given('happy go lucky').expect('happy%20go%20lucky');
-    given('do-right').expect('do--right');
-    given('it_is_a_snake').expect('it__is__a__snake');
-  });
+    given('foo').expect('foo')
+    given('').expect('')
+    given('happy go lucky').expect('happy%20go%20lucky')
+    given('do-right').expect('do--right')
+    given('it_is_a_snake').expect('it__is__a__snake')
+  })
 
   test(staticBadgeUrl, () => {
-    given('http://img.example.com', 'foo', 'bar', 'blue', { style: 'plastic'})
-      .expect('http://img.example.com/badge/foo-bar-blue.svg?style=plastic');
-  });
+    given('http://img.example.com', 'foo', 'bar', 'blue', {
+      style: 'plastic',
+    }).expect('http://img.example.com/badge/foo-bar-blue.svg?style=plastic')
+  })
 
   test(dynamicBadgeUrl, () => {
-    const dataUrl = 'http://example.com/foo.json';
-    const query = '$.bar';
-    const prefix = 'value: ';
+    const dataUrl = 'http://example.com/foo.json'
+    const query = '$.bar'
+    const prefix = 'value: '
 
-    given(
-      'http://img.example.com',
-      'json',
-      'foo',
-      dataUrl,
-      query,
-      { prefix, style: 'plastic' }
-    ).expect([
-      'http://img.example.com/badge/dynamic/json.svg',
-      '?label=foo',
-      `&url=${encodeURIComponent(dataUrl)}`,
-      `&query=${encodeURIComponent(query)}`,
-      `&prefix=${encodeURIComponent(prefix)}`,
-      '&style=plastic',
-    ].join(''))
-  });
-});
+    given('http://img.example.com', 'json', 'foo', dataUrl, query, {
+      prefix,
+      style: 'plastic',
+    }).expect(
+      [
+        'http://img.example.com/badge/dynamic/json.svg',
+        '?label=foo',
+        `&url=${encodeURIComponent(dataUrl)}`,
+        `&query=${encodeURIComponent(query)}`,
+        `&prefix=${encodeURIComponent(prefix)}`,
+        '&style=plastic',
+      ].join('')
+    )
+  })
+})
diff --git a/frontend/lib/generate-image-markup.js b/frontend/lib/generate-image-markup.js
index ff991a9e0542bcee8bdfda4d611ecb45119b83ef..31b3d022125c06393a856d77bc21b1c8d951885c 100644
--- a/frontend/lib/generate-image-markup.js
+++ b/frontend/lib/generate-image-markup.js
@@ -1,74 +1,75 @@
 export function markdown(badgeUri, link, title) {
-  const withoutLink = `![${title || ''}](${badgeUri})`;
+  const withoutLink = `![${title || ''}](${badgeUri})`
   if (link) {
-    return `[${withoutLink}](${link})`;
+    return `[${withoutLink}](${link})`
   } else {
-    return withoutLink;
+    return withoutLink
   }
 }
 
 export function reStructuredText(badgeUri, link, title) {
-  let result = `.. image:: ${badgeUri}`;
+  let result = `.. image:: ${badgeUri}`
   if (title) {
-    result += `   :alt: ${title}`;
+    result += `   :alt: ${title}`
   }
   if (link) {
-    result += `   :target: ${link}`;
+    result += `   :target: ${link}`
   }
-  return result;
+  return result
 }
 
 function quoteAsciiDocAttribute(attr) {
   if (typeof attr === 'string') {
-    const withQuotesEscaped = attr.replace('"', '\\"');
-    return `"${withQuotesEscaped}"`;
+    const withQuotesEscaped = attr.replace('"', '\\"')
+    return `"${withQuotesEscaped}"`
   } else if (attr == null) {
-    return 'None';
+    return 'None'
   } else {
-    return attr;
+    return attr
   }
 }
 
 // lodash.mapvalues is huge!
 function mapValues(obj, iteratee) {
-  const result = {};
+  const result = {}
   for (const k in obj) {
-    result[k] = iteratee(obj[k]);
+    result[k] = iteratee(obj[k])
   }
-  return result;
+  return result
 }
 
 export function renderAsciiDocAttributes(positional, named) {
   // http://asciidoc.org/userguide.html#X21
-  const needsQuoting = positional.some(attr => attr.includes(',')) ||
-    Object.keys(named).length > 0;
+  const needsQuoting =
+    positional.some(attr => attr.includes(',')) || Object.keys(named).length > 0
 
   if (needsQuoting) {
-    positional = positional.map(attr => quoteAsciiDocAttribute(attr));
-    named = mapValues(named, attr => quoteAsciiDocAttribute(attr));
+    positional = positional.map(attr => quoteAsciiDocAttribute(attr))
+    named = mapValues(named, attr => quoteAsciiDocAttribute(attr))
   }
 
-  const items = positional
-    .concat(Object.entries(named).map(([k, v]) => `${k}=${v}`));
+  const items = positional.concat(
+    Object.entries(named).map(([k, v]) => `${k}=${v}`)
+  )
 
   if (items.length) {
-    return `[${items.join(',')}]`;
+    return `[${items.join(',')}]`
   } else {
-    return '';
+    return ''
   }
 }
 
 export function asciiDoc(badgeUri, link, title) {
-  const positional = title ? [title] : [];
-  const named = link ? { link } : {};
-  const attrs = renderAsciiDocAttributes(positional, named);
-  return `image:${badgeUri}${attrs}`;
+  const positional = title ? [title] : []
+  const named = link ? { link } : {}
+  const attrs = renderAsciiDocAttributes(positional, named)
+  return `image:${badgeUri}${attrs}`
 }
 
 export default function generateAllMarkup(badgeUri, link, title) {
   // This is a wee bit "clever". It runs each of the three functions on the
   // parameters provided, and returns the result in an object.
-  return mapValues(
-    { markdown, reStructuredText, asciiDoc },
-    fn => fn(badgeUri, link, title));
+  return mapValues({ markdown, reStructuredText, asciiDoc }, fn =>
+    fn(badgeUri, link, title)
+  )
 }
diff --git a/frontend/lib/prepare-examples.js b/frontend/lib/prepare-examples.js
index 787d395a1e44d7070b7842a71732470da4444439..4293d2aff7ebe4a7f7b52721054821602a84355f 100644
--- a/frontend/lib/prepare-examples.js
+++ b/frontend/lib/prepare-examples.js
@@ -1,36 +1,45 @@
-import escapeStringRegexp from 'escape-string-regexp';
+import escapeStringRegexp from 'escape-string-regexp'
 
 export function exampleMatchesRegex(example, regex) {
-  const { title, keywords } = example;
-  const haystack = [title].concat(keywords).join(' ');
-  return regex.test(haystack);
+  const { title, keywords } = example
+  const haystack = [title].concat(keywords).join(' ')
+  return regex.test(haystack)
 }
 
 export function predicateFromQuery(query) {
   if (query) {
-    const escaped = escapeStringRegexp(query);
-    const regex = new RegExp(escaped, 'i'); // Case-insensitive.
-    return example => exampleMatchesRegex(example, regex);
+    const escaped = escapeStringRegexp(query)
+    const regex = new RegExp(escaped, 'i') // Case-insensitive.
+    return example => exampleMatchesRegex(example, regex)
   } else {
-    return () => true;
+    return () => true
   }
 }
 
 export function mapExamples(categories, iteratee) {
-  return categories
-    .map(({ category, examples }) => ({
-      category,
-      examples: iteratee(examples),
-    }))
-    // Remove empty categories.
-    .filter(({ category, examples }) => examples.length > 0);
+  return (
+    categories
+      .map(({ category, examples }) => ({
+        category,
+        examples: iteratee(examples),
+      }))
+      // Remove empty categories.
+      .filter(({ category, examples }) => examples.length > 0)
+  )
 }
 
 export function prepareExamples(categories, predicateProvider) {
-  let nextKey = 0;
-  return mapExamples(categories, examples => examples.map(example => Object.assign({
-    shouldDisplay: () => predicateProvider()(example),
-    // Assign each example a unique ID.
-    key: nextKey++,
-  }, example)));
+  let nextKey = 0
+  return mapExamples(categories, examples =>
+    examples.map(example =>
+      Object.assign(
+        {
+          shouldDisplay: () => predicateProvider()(example),
+          // Assign each example a unique ID.
+          key: nextKey++,
+        },
+        example
+      )
+    )
+  )
 }
diff --git a/frontend/lib/prepare-examples.spec.js b/frontend/lib/prepare-examples.spec.js
index eedf187f0f8e6e746b754800e83936ad55850bcf..57b61caeaade913459156a99fd789d9d52dfcb7e 100644
--- a/frontend/lib/prepare-examples.spec.js
+++ b/frontend/lib/prepare-examples.spec.js
@@ -1,20 +1,18 @@
-import { test, given, forCases } from 'sazerac';
-import { predicateFromQuery } from './prepare-examples';
+import { test, given, forCases } from 'sazerac'
+import { predicateFromQuery } from './prepare-examples'
 
 describe('Badge example functions', function() {
-  const exampleMatchesQuery =
-    (example, query) => predicateFromQuery(query)(example);
+  const exampleMatchesQuery = (example, query) =>
+    predicateFromQuery(query)(example)
 
   test(exampleMatchesQuery, () => {
-    forCases([
-      given({ title: 'node version' }, 'npm'),
-    ]).expect(false);
+    forCases([given({ title: 'node version' }, 'npm')]).expect(false)
 
     forCases([
       given({ title: 'node version', keywords: ['npm'] }, 'node'),
       given({ title: 'node version', keywords: ['npm'] }, 'npm'),
       // https://github.com/badges/shields/issues/1578
       given({ title: 'c++ is the best language' }, 'c++'),
-    ]).expect(true);
-  });
-});
+    ]).expect(true)
+  })
+})
diff --git a/frontend/lib/resolve-url.js b/frontend/lib/resolve-url.js
index f59f03f0c7c3fc5a132d0eb9badf6bfd741460b2..17103a687238ac58d2882553ef6e8579f493051d 100644
--- a/frontend/lib/resolve-url.js
+++ b/frontend/lib/resolve-url.js
@@ -2,13 +2,13 @@
 // right thing. Previously this was based on url-path, which patched around
 // the URL API. This caused problems in Firefox 57, but only in the production
 // build.
-import { resolve, parse, format } from 'url';
+import { resolve, parse, format } from 'url'
 
 // baseUrl and queryParams are optional.
-export default function resolveUrl (url, baseUrl, queryParams) {
-  const resolved = baseUrl ? resolve(baseUrl, url) : url;
-  const parsed = parse(resolved, /* parseQueryString */ true);
-  parsed.query = Object.assign({}, parsed.query, queryParams);
-  delete parsed.search;
-  return format(parsed);
+export default function resolveUrl(url, baseUrl, queryParams) {
+  const resolved = baseUrl ? resolve(baseUrl, url) : url
+  const parsed = parse(resolved, /* parseQueryString */ true)
+  parsed.query = Object.assign({}, parsed.query, queryParams)
+  delete parsed.search
+  return format(parsed)
 }
diff --git a/frontend/lib/resolve-url.spec.js b/frontend/lib/resolve-url.spec.js
index f4c824bc14ce426063bdf1cabff7cd7f169aa0fa..25c5ffb9af3f8a1d24c4f6444217e57b2eb5f47e 100644
--- a/frontend/lib/resolve-url.spec.js
+++ b/frontend/lib/resolve-url.spec.js
@@ -1,5 +1,5 @@
-import { test, given, forCases } from 'sazerac';
-import resolveUrl from './resolve-url';
+import { test, given, forCases } from 'sazerac'
+import resolveUrl from './resolve-url'
 
 describe('URL resolver', function() {
   test(resolveUrl, () => {
@@ -20,10 +20,10 @@ describe('URL resolver', function() {
       given('/bar', 'http://foo/'),
     ]).expect('http://foo/bar')
 
-    given('/foo/bar', '/baz', { baz: 'bazinga' })
-      .expect('/foo/bar?baz=bazinga');
+    given('/foo/bar', '/baz', { baz: 'bazinga' }).expect('/foo/bar?baz=bazinga')
 
-    given('/foo/bar?thing=1', undefined, { other: '2' })
-      .expect('/foo/bar?thing=1&other=2');
+    given('/foo/bar?thing=1', undefined, { other: '2' }).expect(
+      '/foo/bar?thing=1&other=2'
+    )
   })
-});
+})
diff --git a/lib/all-badge-examples.js b/lib/all-badge-examples.js
index f44c5031278564db389709440aaf7689d320838d..79bfab146fe5a6da706218866b249df1ba1871df 100644
--- a/lib/all-badge-examples.js
+++ b/lib/all-badge-examples.js
@@ -1,6 +1,6 @@
-'use strict';
+'use strict'
 
-const { loadServiceClasses } = require('../services');
+const { loadServiceClasses } = require('../services')
 
 const visualStudioTeamServicesDoc = `
 <p>
@@ -22,7 +22,7 @@ const visualStudioTeamServicesDoc = `
   Your badge will then have the form
   <code>https://img.shields.io/vso/build/TEAM_NAME/PROJECT_ID/BUILD_DEFINITION_ID</code>.
 </p>
-`;
+`
 
 const websiteDoc = `
 <p>
@@ -84,7 +84,7 @@ const websiteDoc = `
     </td></tr>
   </tbody></table>
 </p>
-`;
+`
 
 const githubDoc = `
 <p>
@@ -94,13 +94,13 @@ const githubDoc = `
   <a href="https://img.shields.io/github-auth">going to this page</a> to add
   Shields as a GitHub application on your GitHub account.
 </p>
-`;
+`
 
 const bugzillaDoc = `
 <p>
   If your Bugzilla badge errors, it might be because you are trying to load a private bug.
 </p>
-`;
+`
 
 const jiraSprintCompletionDoc = `
 <p>
@@ -108,7 +108,7 @@ const jiraSprintCompletionDoc = `
   right click on your sprint name and get the value of
   <code>data-sprint-id</code>.
 </p>
-`;
+`
 
 const allBadgeExamples = [
   {
@@ -1754,33 +1754,33 @@ const allBadgeExamples = [
       },
     ],
   },
-];
+]
 
 function findCategory(wantedCategory) {
   return allBadgeExamples.find(
     thisCat => thisCat.category.id === wantedCategory
-  );
+  )
 }
 
 function loadExamples() {
   loadServiceClasses().forEach(ServiceClass => {
-    const category = findCategory(ServiceClass.category);
+    const category = findCategory(ServiceClass.category)
     if (category === undefined) {
       if (ServiceClass.category === 'debug') {
         // we don't want to show debug services on the examples page
-        return;
+        return
       }
       throw Error(
         `Unknown category ${ServiceClass.category} referenced in ${
           ServiceClass.name
         }`
-      );
+      )
     }
-    const prepared = ServiceClass.prepareExamples();
-    category.examples = category.examples.concat(prepared);
-  });
+    const prepared = ServiceClass.prepareExamples()
+    category.examples = category.examples.concat(prepared)
+  })
 }
-loadExamples();
+loadExamples()
 
-module.exports = allBadgeExamples;
-module.exports.findCategory = findCategory;
+module.exports = allBadgeExamples
+module.exports.findCategory = findCategory
diff --git a/lib/all-badge-examples.spec.js b/lib/all-badge-examples.spec.js
index eb3dc77406b2d3c00fa4f5d15e8d9586f4857d71..fd4758959fbf6bca4f493442b9adbb32f5698e0f 100644
--- a/lib/all-badge-examples.spec.js
+++ b/lib/all-badge-examples.spec.js
@@ -1,15 +1,16 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
+const { expect } = require('chai')
 
-const allBadgeExamples = require('./all-badge-examples');
+const allBadgeExamples = require('./all-badge-examples')
 
-describe('The badge examples', function () {
-  it('should include AppVeyor, which is added automatically', function () {
-    const { examples } = allBadgeExamples.findCategory('build');
+describe('The badge examples', function() {
+  it('should include AppVeyor, which is added automatically', function() {
+    const { examples } = allBadgeExamples.findCategory('build')
 
-    const appVeyorBuildExamples = examples.filter(ex => ex.title.includes('AppVeyor'))
-      .filter(ex => ! ex.title.includes('tests'));
+    const appVeyorBuildExamples = examples
+      .filter(ex => ex.title.includes('AppVeyor'))
+      .filter(ex => !ex.title.includes('tests'))
 
     expect(appVeyorBuildExamples).to.deep.equal([
       {
@@ -24,6 +25,6 @@ describe('The badge examples', function () {
         exampleUri: undefined,
         documentation: undefined,
       },
-    ]);
-  });
-});
+    ])
+  })
+})
diff --git a/lib/analytics.js b/lib/analytics.js
index ecff6ba7b7bd2f06e69aa583085ea0d5e29e5dc9..3f4c88c68f4883f1785a1e7c74a54c5b6d0991c2 100644
--- a/lib/analytics.js
+++ b/lib/analytics.js
@@ -1,137 +1,141 @@
-'use strict';
+'use strict'
 
-const fs = require('fs');
+const fs = require('fs')
 
 // We can either use a process-wide object regularly saved to a JSON file,
 // or a Redis equivalent (for multi-process / when the filesystem is unreliable.
-let redis;
-let useRedis = false;
+let redis
+let useRedis = false
 if (process.env.REDISTOGO_URL) {
-  const redisToGo = require('url').parse(process.env.REDISTOGO_URL);
-  redis = require('redis').createClient(redisToGo.port, redisToGo.hostname);
-  redis.auth(redisToGo.auth.split(':')[1]);
-  useRedis = true;
+  const redisToGo = require('url').parse(process.env.REDISTOGO_URL)
+  redis = require('redis').createClient(redisToGo.port, redisToGo.hostname)
+  redis.auth(redisToGo.auth.split(':')[1])
+  useRedis = true
 }
 
-let analytics = {};
-let autosaveIntervalId;
+let analytics = {}
+let autosaveIntervalId
 
-const analyticsPath = process.env.SHIELDS_ANALYTICS_FILE || './analytics.json';
+const analyticsPath = process.env.SHIELDS_ANALYTICS_FILE || './analytics.json'
 
 function performAutosave() {
-  const contents = JSON.stringify(analytics);
+  const contents = JSON.stringify(analytics)
   if (useRedis) {
-    redis.set(analyticsPath, contents);
+    redis.set(analyticsPath, contents)
   } else {
-    fs.writeFileSync(analyticsPath, contents);
+    fs.writeFileSync(analyticsPath, contents)
   }
 }
 
 function scheduleAutosaving() {
-  const analyticsAutoSavePeriod = 10000;
-  autosaveIntervalId = setInterval(performAutosave, analyticsAutoSavePeriod);
+  const analyticsAutoSavePeriod = 10000
+  autosaveIntervalId = setInterval(performAutosave, analyticsAutoSavePeriod)
 }
 
 // For a clean shutdown.
 function cancelAutosaving() {
   if (autosaveIntervalId) {
-    clearInterval(autosaveIntervalId);
-    autosaveIntervalId = null;
+    clearInterval(autosaveIntervalId)
+    autosaveIntervalId = null
   }
-  performAutosave();
+  performAutosave()
 }
 
 function defaultAnalytics() {
-  const analytics = Object.create(null);
+  const analytics = Object.create(null)
   // In case something happens on the 36th.
-  analytics.vendorMonthly = new Array(36);
-  resetMonthlyAnalytics(analytics.vendorMonthly);
-  analytics.rawMonthly = new Array(36);
-  resetMonthlyAnalytics(analytics.rawMonthly);
-  analytics.vendorFlatMonthly = new Array(36);
-  resetMonthlyAnalytics(analytics.vendorFlatMonthly);
-  analytics.rawFlatMonthly = new Array(36);
-  resetMonthlyAnalytics(analytics.rawFlatMonthly);
-  analytics.vendorFlatSquareMonthly = new Array(36);
-  resetMonthlyAnalytics(analytics.vendorFlatSquareMonthly);
-  analytics.rawFlatSquareMonthly = new Array(36);
-  resetMonthlyAnalytics(analytics.rawFlatSquareMonthly);
-  return analytics;
+  analytics.vendorMonthly = new Array(36)
+  resetMonthlyAnalytics(analytics.vendorMonthly)
+  analytics.rawMonthly = new Array(36)
+  resetMonthlyAnalytics(analytics.rawMonthly)
+  analytics.vendorFlatMonthly = new Array(36)
+  resetMonthlyAnalytics(analytics.vendorFlatMonthly)
+  analytics.rawFlatMonthly = new Array(36)
+  resetMonthlyAnalytics(analytics.rawFlatMonthly)
+  analytics.vendorFlatSquareMonthly = new Array(36)
+  resetMonthlyAnalytics(analytics.vendorFlatSquareMonthly)
+  analytics.rawFlatSquareMonthly = new Array(36)
+  resetMonthlyAnalytics(analytics.rawFlatSquareMonthly)
+  return analytics
 }
 
 function load() {
-  const defaultAnalyticsObject = defaultAnalytics();
+  const defaultAnalyticsObject = defaultAnalytics()
   if (useRedis) {
     redis.get(analyticsPath, function(err, value) {
       if (err == null && value != null) {
         // if/try/return trick:
         // if error, then the rest of the function is run.
         try {
-          analytics = JSON.parse(value);
+          analytics = JSON.parse(value)
           // Extend analytics with a new value.
           for (const key in defaultAnalyticsObject) {
             if (!(key in analytics)) {
-              analytics[key] = defaultAnalyticsObject[key];
+              analytics[key] = defaultAnalyticsObject[key]
             }
           }
-          return;
-        } catch(e) {
-          console.error('Invalid Redis analytics, resetting.');
-          console.error(e);
+          return
+        } catch (e) {
+          console.error('Invalid Redis analytics, resetting.')
+          console.error(e)
         }
       }
-      analytics = defaultAnalyticsObject;
-    });
+      analytics = defaultAnalyticsObject
+    })
   } else {
     // Not using Redis.
     try {
-      analytics = JSON.parse(fs.readFileSync(analyticsPath));
+      analytics = JSON.parse(fs.readFileSync(analyticsPath))
       // Extend analytics with a new value.
       for (const key in defaultAnalyticsObject) {
         if (!(key in analytics)) {
-          analytics[key] = defaultAnalyticsObject[key];
+          analytics[key] = defaultAnalyticsObject[key]
         }
       }
-    } catch(e) {
+    } catch (e) {
       if (e.code !== 'ENOENT') {
-        console.error('Invalid JSON file for analytics, resetting.');
-        console.error(e);
+        console.error('Invalid JSON file for analytics, resetting.')
+        console.error(e)
       }
-      analytics = defaultAnalyticsObject;
+      analytics = defaultAnalyticsObject
     }
   }
 }
 
-let lastDay = (new Date()).getDate();
+let lastDay = new Date().getDate()
 function resetMonthlyAnalytics(monthlyAnalytics) {
   for (let i = 0; i < monthlyAnalytics.length; i++) {
-    monthlyAnalytics[i] = 0;
+    monthlyAnalytics[i] = 0
   }
 }
 function incrMonthlyAnalytics(monthlyAnalytics) {
   try {
-    const currentDay = (new Date()).getDate();
+    const currentDay = new Date().getDate()
     // If we changed month, reset empty days.
     while (lastDay !== currentDay) {
       // Assumption: at least a hit a month.
-      lastDay = (lastDay + 1) % monthlyAnalytics.length;
-      monthlyAnalytics[lastDay] = 0;
+      lastDay = (lastDay + 1) % monthlyAnalytics.length
+      monthlyAnalytics[lastDay] = 0
     }
-    monthlyAnalytics[currentDay]++;
-  } catch(e) { console.error(e.stack); }
+    monthlyAnalytics[currentDay]++
+  } catch (e) {
+    console.error(e.stack)
+  }
 }
 
 function noteRequest(queryParams, match) {
-  incrMonthlyAnalytics(analytics.vendorMonthly);
+  incrMonthlyAnalytics(analytics.vendorMonthly)
   if (queryParams.style === 'flat') {
-    incrMonthlyAnalytics(analytics.vendorFlatMonthly);
+    incrMonthlyAnalytics(analytics.vendorFlatMonthly)
   } else if (queryParams.style === 'flat-square') {
-    incrMonthlyAnalytics(analytics.vendorFlatSquareMonthly);
+    incrMonthlyAnalytics(analytics.vendorFlatSquareMonthly)
   }
 }
 
-function setRoutes (server) {
-  server.ajax.on('analytics/v1', (json, end) => { end(analytics); });
+function setRoutes(server) {
+  server.ajax.on('analytics/v1', (json, end) => {
+    end(analytics)
+  })
 }
 
 module.exports = {
@@ -139,5 +143,5 @@ module.exports = {
   scheduleAutosaving,
   cancelAutosaving,
   noteRequest,
-  setRoutes
-};
+  setRoutes,
+}
diff --git a/lib/badge-cli.js b/lib/badge-cli.js
index 2cc55d998ac4b631a162c57ea9ddd3c4a0f9d92e..7dd2b1fac4a0d375cd296eef715ea40439f9a03b 100755
--- a/lib/badge-cli.js
+++ b/lib/badge-cli.js
@@ -1,87 +1,92 @@
 #!/usr/bin/env node
 
-'use strict';
+'use strict'
 
-const { PDFKitTextMeasurer } = require('./text-measurer');
-const { makeBadge } = require('./make-badge');
-const svg2img = require('./svg-to-img');
-const colorscheme = require('./colorscheme.json');
-const defaults = require('./defaults');
+const { PDFKitTextMeasurer } = require('./text-measurer')
+const { makeBadge } = require('./make-badge')
+const svg2img = require('./svg-to-img')
+const colorscheme = require('./colorscheme.json')
+const defaults = require('./defaults')
 
 if (process.argv.length < 4) {
-  console.log('Usage: badge subject status [:colorscheme] [.output] [@style]');
-  console.log('Or:    badge subject status right-color [left-color] [.output] [@style]');
-  console.log();
-  console.log('  colorscheme: one of '
-      + Object.keys(colorscheme).join(', ') + '.');
-  console.log('  left-color, right-color:');
-  console.log('    #xxx (three hex digits)');
-  console.log('    #xxxxxx (six hex digits)');
-  console.log('    color (CSS color)');
-  console.log('  output:');
-  console.log('    svg, png, jpg, or gif');
-  console.log();
-  console.log('Eg: badge cactus grown :green @flat');
-  console.log();
-  process.exit();
+  console.log('Usage: badge subject status [:colorscheme] [.output] [@style]')
+  console.log(
+    'Or:    badge subject status right-color [left-color] [.output] [@style]'
+  )
+  console.log()
+  console.log(
+    '  colorscheme: one of ' + Object.keys(colorscheme).join(', ') + '.'
+  )
+  console.log('  left-color, right-color:')
+  console.log('    #xxx (three hex digits)')
+  console.log('    #xxxxxx (six hex digits)')
+  console.log('    color (CSS color)')
+  console.log('  output:')
+  console.log('    svg, png, jpg, or gif')
+  console.log()
+  console.log('Eg: badge cactus grown :green @flat')
+  console.log()
+  process.exit()
 }
 
-const fontPath = process.env.FONT_PATH || defaults.font.path;
+const fontPath = process.env.FONT_PATH || defaults.font.path
 
 // Find a format specifier.
-let format = 'svg';
-let style = '';
+let format = 'svg'
+let style = ''
 for (let i = 4; i < process.argv.length; i++) {
   if (process.argv[i][0] === '.') {
-    format = process.argv[i].slice(1);
-    process.argv.splice(i, 1);
-    continue;
+    format = process.argv[i].slice(1)
+    process.argv.splice(i, 1)
+    continue
   }
   if (process.argv[i][0] === '@') {
-    style = process.argv[i].slice(1);
-    process.argv.splice(i, 1);
-    continue;
+    style = process.argv[i].slice(1)
+    process.argv.splice(i, 1)
+    continue
   }
 }
 
-const subject = process.argv[2];
-const status = process.argv[3];
-let color = process.argv[4] || ':green';
-const colorA = process.argv[5];
+const subject = process.argv[2]
+const status = process.argv[3]
+let color = process.argv[4] || ':green'
+const colorA = process.argv[5]
 
-const badgeData = {text: [subject, status], format: format};
+const badgeData = { text: [subject, status], format: format }
 if (style) {
-  badgeData.template = style;
+  badgeData.template = style
 }
 
 if (color[0] === ':') {
-  color = color.slice(1);
+  color = color.slice(1)
   if (colorscheme[color] == null) {
     // Colorscheme not found.
-    console.error('Invalid color scheme.');
-    process.exit(1);
+    console.error('Invalid color scheme.')
+    process.exit(1)
   }
-  badgeData.colorscheme = color;
+  badgeData.colorscheme = color
 } else {
-  badgeData.colorB = color;
-  if (colorA) { badgeData.colorA = colorA; }
+  badgeData.colorB = color
+  if (colorA) {
+    badgeData.colorA = colorA
+  }
 }
 
 async function main() {
   // The widths are going to be off if Helvetica-Bold is used, though this
   // should print a warning.
-  const measurer = new PDFKitTextMeasurer(fontPath, 'Helvetica-Bold');
-  const svg = makeBadge(measurer, badgeData);
+  const measurer = new PDFKitTextMeasurer(fontPath, 'Helvetica-Bold')
+  const svg = makeBadge(measurer, badgeData)
 
   if (/png|jpg|gif/.test(format)) {
-    const data = await svg2img(svg, format);
-    process.stdout.write(data);
+    const data = await svg2img(svg, format)
+    process.stdout.write(data)
   } else {
-    console.log(svg);
+    console.log(svg)
   }
 }
 
-(async () => {
+;(async () => {
   try {
     await main()
   } catch (e) {
diff --git a/lib/badge-cli.spec.js b/lib/badge-cli.spec.js
index 8e99ac7704b52dfab3d60c2bbdb646edc94380f6..8464633e8e94e005a0df6314946d86726d1bdf93 100644
--- a/lib/badge-cli.spec.js
+++ b/lib/badge-cli.spec.js
@@ -1,53 +1,55 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const isPng = require('is-png');
-const isSvg = require('is-svg');
-const { spawn } = require('child-process-promise');
+const { expect } = require('chai')
+const isPng = require('is-png')
+const isSvg = require('is-svg')
+const { spawn } = require('child-process-promise')
 
 // https://github.com/badges/shields/pull/1419#discussion_r159957055
-require('./register-chai-plugins.spec');
+require('./register-chai-plugins.spec')
 
-function runCli (args) {
+function runCli(args) {
   return spawn('node', ['lib/badge-cli.js', ...args], { capture: ['stdout'] })
 }
 
-describe('The CLI', function () {
-  it('should provide a help message', async function () {
-    const { stdout } = await runCli([]);
-    expect(stdout).to.startWith('Usage');
-  });
+describe('The CLI', function() {
+  it('should provide a help message', async function() {
+    const { stdout } = await runCli([])
+    expect(stdout).to.startWith('Usage')
+  })
 
-  it('should produce default badges', async function () {
-    const { stdout } = await runCli(['cactus', 'grown']);
+  it('should produce default badges', async function() {
+    const { stdout } = await runCli(['cactus', 'grown'])
     expect(stdout)
       .to.satisfy(isSvg)
       .and.to.include('cactus')
-      .and.to.include('grown');
-  });
+      .and.to.include('grown')
+  })
 
-  it('should produce colorschemed badges', async function () {
-    const { stdout } = await runCli(['cactus', 'grown', ':green']);
-    expect(stdout).to.satisfy(isSvg);
-  });
+  it('should produce colorschemed badges', async function() {
+    const { stdout } = await runCli(['cactus', 'grown', ':green'])
+    expect(stdout).to.satisfy(isSvg)
+  })
 
-  it('should produce right-color badges', async function () {
-    const { stdout } = await runCli(['cactus', 'grown', '#abcdef']);
+  it('should produce right-color badges', async function() {
+    const { stdout } = await runCli(['cactus', 'grown', '#abcdef'])
     expect(stdout)
       .to.satisfy(isSvg)
-      .and.to.include('#abcdef');
-  });
+      .and.to.include('#abcdef')
+  })
 
-  it('should produce PNG badges', async function () {
-    const child = runCli(['cactus', 'grown', '.png']);
+  it('should produce PNG badges', async function() {
+    const child = runCli(['cactus', 'grown', '.png'])
 
     // The buffering done by `child-process-promise` doesn't seem correctly to
     // handle binary data.
-    let chunk;
-    child.childProcess.stdout.once('data', data => { chunk = data; });
+    let chunk
+    child.childProcess.stdout.once('data', data => {
+      chunk = data
+    })
 
-    await child;
+    await child
 
-    expect(chunk).to.satisfy(isPng);
-  });
-});
+    expect(chunk).to.satisfy(isPng)
+  })
+})
diff --git a/lib/badge-data.js b/lib/badge-data.js
index 8ac9f7db97b8dba21808edfb78f45fd970c5bf61..68abf42f92108193d0f95857f05293d4bd5f8445 100644
--- a/lib/badge-data.js
+++ b/lib/badge-data.js
@@ -1,109 +1,120 @@
-'use strict';
+'use strict'
 
-const isCSSColor = require('is-css-color');
-const logos = require('./load-logos')();
-const simpleIcons = require('./load-simple-icons')();
-const {
-  svg2base64,
-  isDataUri,
-} = require('./logo-helper');
-const colorschemes = require('./colorscheme.json');
+const isCSSColor = require('is-css-color')
+const logos = require('./load-logos')()
+const simpleIcons = require('./load-simple-icons')()
+const { svg2base64, isDataUri } = require('./logo-helper')
+const colorschemes = require('./colorscheme.json')
 
 function toArray(val) {
   if (val === undefined) {
-    return [];
+    return []
   } else if (Object(val) instanceof Array) {
-    return val;
+    return val
   } else {
-    return [val];
+    return [val]
   }
 }
 
 function prependPrefix(s, prefix) {
   if (s === undefined) {
-    return undefined;
+    return undefined
   }
 
-  s = '' + s;
+  s = '' + s
 
   if (s.startsWith(prefix)) {
-    return s;
+    return s
   } else {
-    return prefix + s;
+    return prefix + s
   }
 }
 
-function isHexColor (s = ''){
-  return /^([\da-f]{3}){1,2}$/i.test(s);
+function isHexColor(s = '') {
+  return /^([\da-f]{3}){1,2}$/i.test(s)
 }
 
 function makeColor(color) {
   if (isHexColor(color)) {
-    return '#' + color;
-  } else if (colorschemes[color] !== undefined){
-    return colorschemes[color].colorB;
-  } else if (isCSSColor(color)){
-    return color;
+    return '#' + color
+  } else if (colorschemes[color] !== undefined) {
+    return colorschemes[color].colorB
+  } else if (isCSSColor(color)) {
+    return color
   } else {
-    return undefined;
+    return undefined
   }
 }
 
 function makeColorB(defaultColor, overrides) {
-  return makeColor(overrides.colorB || defaultColor);
+  return makeColor(overrides.colorB || defaultColor)
 }
 
 function setBadgeColor(badgeData, color) {
   if (isHexColor(color)) {
-    badgeData.colorB = '#' + color;
-    delete badgeData.colorscheme;
-  } else if (colorschemes[color] !== undefined){
-    badgeData.colorscheme = color;
-    delete badgeData.colorB;
-  } else if (isCSSColor(color)){
-    badgeData.colorB = color;
-    delete badgeData.colorscheme;
+    badgeData.colorB = '#' + color
+    delete badgeData.colorscheme
+  } else if (colorschemes[color] !== undefined) {
+    badgeData.colorscheme = color
+    delete badgeData.colorB
+  } else if (isCSSColor(color)) {
+    badgeData.colorB = color
+    delete badgeData.colorscheme
   } else {
-    badgeData.colorscheme = 'red';
-    delete badgeData.colorB;
+    badgeData.colorscheme = 'red'
+    delete badgeData.colorB
   }
-  return badgeData;
+  return badgeData
 }
 
 function makeLabel(defaultLabel, overrides) {
-  return '' + (overrides.label === undefined ? defaultLabel || '' : overrides.label);
+  return (
+    '' + (overrides.label === undefined ? defaultLabel || '' : overrides.label)
+  )
 }
 
-function getShieldsIcon(icon = '', color = ''){
-  icon = typeof icon === 'string' ? icon.toLowerCase() : '';
-  if (!logos[icon]){
-    return undefined;
+function getShieldsIcon(icon = '', color = '') {
+  icon = typeof icon === 'string' ? icon.toLowerCase() : ''
+  if (!logos[icon]) {
+    return undefined
   }
-  color = makeColor(color);
-  return color ? logos[icon].svg.replace(/fill="(.+?)"/g, `fill="${color}"`) : logos[icon].base64;
+  color = makeColor(color)
+  return color
+    ? logos[icon].svg.replace(/fill="(.+?)"/g, `fill="${color}"`)
+    : logos[icon].base64
 }
 
-function getSimpleIcon(icon = '', color = null){
-  icon = typeof icon === 'string' ? icon.toLowerCase().replace(/ /g, '-') : '';
-  if (!simpleIcons[icon]){
-    return undefined;
+function getSimpleIcon(icon = '', color = null) {
+  icon = typeof icon === 'string' ? icon.toLowerCase().replace(/ /g, '-') : ''
+  if (!simpleIcons[icon]) {
+    return undefined
   }
-  color = makeColor(color);
-  return color ? simpleIcons[icon].svg.replace('<svg', `<svg fill="${color}"`) : simpleIcons[icon].base64;
+  color = makeColor(color)
+  return color
+    ? simpleIcons[icon].svg.replace('<svg', `<svg fill="${color}"`)
+    : simpleIcons[icon].base64
 }
 
 function makeLogo(defaultNamedLogo, overrides) {
-  if (overrides.logo === undefined){
-    return svg2base64(getShieldsIcon(defaultNamedLogo, overrides.logoColor) || getSimpleIcon(defaultNamedLogo, overrides.logoColor));
+  if (overrides.logo === undefined) {
+    return svg2base64(
+      getShieldsIcon(defaultNamedLogo, overrides.logoColor) ||
+        getSimpleIcon(defaultNamedLogo, overrides.logoColor)
+    )
   }
 
   // +'s are replaced with spaces when used in query params, this returns them to +'s, then removes remaining whitespace - #1546
-  const maybeDataUri = prependPrefix(overrides.logo, 'data:').replace(/ /g, '+').replace(/\s/g, '');
+  const maybeDataUri = prependPrefix(overrides.logo, 'data:')
+    .replace(/ /g, '+')
+    .replace(/\s/g, '')
 
   if (isDataUri(maybeDataUri)) {
-    return maybeDataUri;
+    return maybeDataUri
   } else {
-    return svg2base64(getShieldsIcon(overrides.logo, overrides.logoColor) || getSimpleIcon(overrides.logo, overrides.logoColor));
+    return svg2base64(
+      getShieldsIcon(overrides.logo, overrides.logoColor) ||
+        getSimpleIcon(overrides.logo, overrides.logoColor)
+    )
   }
 }
 
@@ -133,7 +144,7 @@ function makeBadgeData(defaultLabel, overrides) {
     links: toArray(overrides.link),
     colorA: makeColor(overrides.colorA),
     colorB: makeColor(overrides.colorB),
-  };
+  }
 }
 
 module.exports = {
@@ -145,5 +156,5 @@ module.exports = {
   makeBadgeData,
   makeColor,
   makeColorB,
-  setBadgeColor
-};
+  setBadgeColor,
+}
diff --git a/lib/badge-data.spec.js b/lib/badge-data.spec.js
index 75fe9d885895c8b1d427381223eaeb99d0590a38..5654f38d801475531803e9f21150f7be6433de2b 100644
--- a/lib/badge-data.spec.js
+++ b/lib/badge-data.spec.js
@@ -1,7 +1,7 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const { test, given, forCases } = require('sazerac');
+const { expect } = require('chai')
+const { test, given, forCases } = require('sazerac')
 const {
   prependPrefix,
   isHexColor,
@@ -9,35 +9,30 @@ const {
   makeLogo,
   makeBadgeData,
   makeColor,
-  setBadgeColor
-} = require('./badge-data');
+  setBadgeColor,
+} = require('./badge-data')
 
 describe('Badge data helpers', function() {
   test(prependPrefix, () => {
-    given('data:image/svg+xml;base64,PHN2ZyB4bWxu', 'data:').expect('data:image/svg+xml;base64,PHN2ZyB4bWxu');
-    given('foobar', 'data:').expect('data:foobar');
-    given(undefined, 'data:').expect(undefined);
-  });
+    given('data:image/svg+xml;base64,PHN2ZyB4bWxu', 'data:').expect(
+      'data:image/svg+xml;base64,PHN2ZyB4bWxu'
+    )
+    given('foobar', 'data:').expect('data:foobar')
+    given(undefined, 'data:').expect(undefined)
+  })
 
   test(isHexColor, () => {
-    forCases([
-      given('f00bae'),
-      given('4c1'),
-    ]).expect(true);
-    forCases([
-      given('f00bar'),
-      given(''),
-      given(undefined),
-    ]).expect(false);
-  });
+    forCases([given('f00bae'), given('4c1')]).expect(true)
+    forCases([given('f00bar'), given(''), given(undefined)]).expect(false)
+  })
 
   test(makeLabel, () => {
-    given('my badge', {}).expect('my badge');
-    given('my badge', { label: 'no, my badge' }).expect('no, my badge');
-    given('my badge', { label: false }).expect('false');
-    given('my badge', { label: 0 }).expect('0');
-    given('my badge', { label: '' }).expect('');
-  });
+    given('my badge', {}).expect('my badge')
+    given('my badge', { label: 'no, my badge' }).expect('no, my badge')
+    given('my badge', { label: false }).expect('false')
+    given('my badge', { label: 0 }).expect('0')
+    given('my badge', { label: '' }).expect('')
+  })
 
   test(makeLogo, () => {
     forCases([
@@ -45,14 +40,15 @@ describe('Badge data helpers', function() {
       given('gratipay', { logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu' }),
       given('gratipay', { logo: 'data:image/svg xml;base64,PHN2ZyB4bWxu' }),
       given('gratipay', { logo: 'data:image/svg+xml;base64,PHN2ZyB\n4bWxu' }),
-    ]).expect('data:image/svg+xml;base64,PHN2ZyB4bWxu');
-    forCases([
-      given('gratipay', { logo: '' }),
-      given(undefined, {}),
-    ]).expect(undefined);
-    given('gratipay', {})
-      .assert('should not be empty', v => expect(v).not.to.be.empty);
-  });
+    ]).expect('data:image/svg+xml;base64,PHN2ZyB4bWxu')
+    forCases([given('gratipay', { logo: '' }), given(undefined, {})]).expect(
+      undefined
+    )
+    given('gratipay', {}).assert(
+      'should not be empty',
+      v => expect(v).not.to.be.empty
+    )
+  })
 
   test(makeBadgeData, () => {
     given('my badge', {
@@ -74,26 +70,38 @@ describe('Badge data helpers', function() {
       links: ['https://example.com/'],
       colorA: '#007ec6',
       colorB: '#f00bae',
-    });
-  });
+    })
+  })
 
   test(makeColor, () => {
-    given('red').expect('#e05d44');
-    given('blue').expect('#007ec6');
-    given('4c1').expect('#4c1');
-    given('f00f00').expect('#f00f00');
-    given('papayawhip').expect('papayawhip');
-    given('purple').expect('purple');
-  });
+    given('red').expect('#e05d44')
+    given('blue').expect('#007ec6')
+    given('4c1').expect('#4c1')
+    given('f00f00').expect('#f00f00')
+    given('papayawhip').expect('papayawhip')
+    given('purple').expect('purple')
+  })
 
   test(setBadgeColor, () => {
-    given({}, 'red').expect({ colorscheme: 'red' });
-    given({}, 'f00f00').expect({ colorB: '#f00f00' });
-    given({ colorB: '#f00f00', colorscheme: 'blue' }, 'red').expect({ colorscheme: 'red' });
-    given({ colorB: '#f00f00', colorscheme: 'blue' }, 'blue').expect({ colorscheme: 'blue' });
-    given({ colorB: '#f00f00', colorscheme: 'blue' }, 'papayawhip').expect({ colorB: 'papayawhip' });
-    given({ colorB: '#f00f00', colorscheme: 'blue' }, 'purple').expect({ colorB: 'purple' });
-    given({ colorB: '#b00b00', colorscheme: 'blue' }, '4c1').expect({ colorB: '#4c1' });
-    given({ colorB: '#b00b00', colorscheme: 'blue' }, 'f00f00').expect({ colorB: '#f00f00' });
-  });
-});
+    given({}, 'red').expect({ colorscheme: 'red' })
+    given({}, 'f00f00').expect({ colorB: '#f00f00' })
+    given({ colorB: '#f00f00', colorscheme: 'blue' }, 'red').expect({
+      colorscheme: 'red',
+    })
+    given({ colorB: '#f00f00', colorscheme: 'blue' }, 'blue').expect({
+      colorscheme: 'blue',
+    })
+    given({ colorB: '#f00f00', colorscheme: 'blue' }, 'papayawhip').expect({
+      colorB: 'papayawhip',
+    })
+    given({ colorB: '#f00f00', colorscheme: 'blue' }, 'purple').expect({
+      colorB: 'purple',
+    })
+    given({ colorB: '#b00b00', colorscheme: 'blue' }, '4c1').expect({
+      colorB: '#4c1',
+    })
+    given({ colorB: '#b00b00', colorscheme: 'blue' }, 'f00f00').expect({
+      colorB: '#f00f00',
+    })
+  })
+})
diff --git a/lib/color-formatters.js b/lib/color-formatters.js
index c54dadb6dda8d47cc4f84dd81ba488d4b6e1b4f6..16b417fc5bb1faff50a6923214c50c7240a89749 100644
--- a/lib/color-formatters.js
+++ b/lib/color-formatters.js
@@ -2,67 +2,67 @@
  * Commonly-used functions for determining the colour to use for a badge,
  * including colours based off download count, version number, etc.
  */
-'use strict';
+'use strict'
 
-const moment = require('moment');
+const moment = require('moment')
 
 function version(version) {
-  if (typeof(version) !== 'string' && typeof(version) !== 'number') {
-    throw new Error(`Can't generate a version color for ${version}`);
+  if (typeof version !== 'string' && typeof version !== 'number') {
+    throw new Error(`Can't generate a version color for ${version}`)
   }
-  version = '' + version;
-  let first = version[0];
+  version = '' + version
+  let first = version[0]
   if (first === 'v') {
-    first = version[1];
+    first = version[1]
   }
   if (first === '0' || /alpha|beta|snapshot|dev|pre/i.test(version)) {
-    return 'orange';
+    return 'orange'
   } else {
-    return 'blue';
+    return 'blue'
   }
 }
 
 function downloadCount(downloads) {
-  return floorCount(downloads, 10, 100, 1000);
+  return floorCount(downloads, 10, 100, 1000)
 }
 
 function coveragePercentage(percentage) {
-  return floorCount(percentage, 80, 90, 100);
+  return floorCount(percentage, 80, 90, 100)
 }
 
 function floorCount(value, yellow, yellowgreen, green) {
   if (value <= 0) {
-    return 'red';
+    return 'red'
   } else if (value < yellow) {
-    return 'yellow';
+    return 'yellow'
   } else if (value < yellowgreen) {
-    return 'yellowgreen';
+    return 'yellowgreen'
   } else if (value < green) {
-    return 'green';
+    return 'green'
   } else {
-    return 'brightgreen';
+    return 'brightgreen'
   }
 }
 
 function letterScore(score) {
   if (score === 'A') {
-    return 'brightgreen';
+    return 'brightgreen'
   } else if (score === 'B') {
-    return 'green';
+    return 'green'
   } else if (score === 'C') {
-    return 'yellowgreen';
+    return 'yellowgreen'
   } else if (score === 'D') {
-    return 'yellow';
+    return 'yellow'
   } else if (score === 'E') {
-    return 'orange';
+    return 'orange'
   } else {
-    return 'red';
+    return 'red'
   }
 }
 
 function colorScale(steps, colors, reversed) {
   if (steps === undefined) {
-    throw Error('When invoking colorScale, steps should be provided.');
+    throw Error('When invoking colorScale, steps should be provided.')
   }
 
   const defaultColors = {
@@ -71,37 +71,39 @@ function colorScale(steps, colors, reversed) {
     3: ['red', 'yellow', 'green', 'brightgreen'],
     4: ['red', 'yellow', 'yellowgreen', 'green', 'brightgreen'],
     5: ['red', 'orange', 'yellow', 'yellowgreen', 'green', 'brightgreen'],
-  };
+  }
 
   if (typeof colors === 'undefined') {
     if (steps.length in defaultColors) {
-      colors = defaultColors[steps.length];
+      colors = defaultColors[steps.length]
     } else {
-      throw Error(`No default colors for ${steps.length} steps.`);
+      throw Error(`No default colors for ${steps.length} steps.`)
     }
   }
 
   if (steps.length !== colors.length - 1) {
-    throw Error('When colors are provided, there should be n + 1 colors for n steps.');
+    throw Error(
+      'When colors are provided, there should be n + 1 colors for n steps.'
+    )
   }
 
   if (reversed) {
-    colors = Array.from(colors).reverse();
+    colors = Array.from(colors).reverse()
   }
 
   return value => {
-    const stepIndex = steps.findIndex(step => value < step);
+    const stepIndex = steps.findIndex(step => value < step)
 
     // For the final step, stepIndex is -1, so in all cases this expression
     // works swimmingly.
-    return colors.slice(stepIndex)[0];
-  };
+    return colors.slice(stepIndex)[0]
+  }
 }
 
 function age(date) {
-  const colorByAge = colorScale([7, 30, 180, 365, 730], undefined, true);
-  const daysElapsed = moment().diff(moment(date), 'days');
-  return colorByAge(daysElapsed);
+  const colorByAge = colorScale([7, 30, 180, 365, 730], undefined, true)
+  const daysElapsed = moment().diff(moment(date), 'days')
+  return colorByAge(daysElapsed)
 }
 
 module.exports = {
@@ -111,5 +113,5 @@ module.exports = {
   floorCount,
   letterScore,
   colorScale,
-  age
-};
+  age,
+}
diff --git a/lib/color-formatters.spec.js b/lib/color-formatters.spec.js
index fe4a0370b73b6a96a1f7419356cd809f4d30e56b..af632b51b0be02dc9c0e951c06baec5c5886034a 100644
--- a/lib/color-formatters.spec.js
+++ b/lib/color-formatters.spec.js
@@ -1,77 +1,85 @@
-'use strict';
+'use strict'
 
-const { test, given, forCases } = require('sazerac');
-const { expect } = require('chai');
+const { test, given, forCases } = require('sazerac')
+const { expect } = require('chai')
 const {
   coveragePercentage,
   colorScale,
   letterScore,
   age,
-  version
-} = require('./color-formatters');
+  version,
+} = require('./color-formatters')
 
 describe('Color formatters', function() {
-  const byPercentage = colorScale([Number.EPSILON, 80, 90, 100]);
+  const byPercentage = colorScale([Number.EPSILON, 80, 90, 100])
 
   test(byPercentage, () => {
-    given(-1).expect('red');
-    given(0).expect('red');
-    given(0.5).expect('yellow');
-    given(1).expect('yellow');
-    given(50).expect('yellow');
-    given(80).expect('yellowgreen');
-    given(85).expect('yellowgreen');
-    given(90).expect('green');
-    given(100).expect('brightgreen');
-    given(101).expect('brightgreen');
+    given(-1).expect('red')
+    given(0).expect('red')
+    given(0.5).expect('yellow')
+    given(1).expect('yellow')
+    given(50).expect('yellow')
+    given(80).expect('yellowgreen')
+    given(85).expect('yellowgreen')
+    given(90).expect('green')
+    given(100).expect('brightgreen')
+    given(101).expect('brightgreen')
 
-    forCases([-1, 0, 0.5, 1, 50, 80, 85, 90, 100, 101]
-      .map(v => given(v).expect(coveragePercentage(v))))
-      .should("return '%s', for parity with coveragePercentage()");
-  });
+    forCases(
+      [-1, 0, 0.5, 1, 50, 80, 85, 90, 100, 101].map(v =>
+        given(v).expect(coveragePercentage(v))
+      )
+    ).should("return '%s', for parity with coveragePercentage()")
+  })
 
-  context('when reversed', function () {
+  context('when reversed', function() {
     test(colorScale([7, 30, 180, 365, 730], undefined, true), () => {
-      given(3).expect('brightgreen');
-      given(7).expect('green');
-      given(10).expect('green');
-      given(60).expect('yellowgreen');
-      given(250).expect('yellow');
-      given(400).expect('orange');
-      given(800).expect('red');
-    });
-  });
+      given(3).expect('brightgreen')
+      given(7).expect('green')
+      given(10).expect('green')
+      given(60).expect('yellowgreen')
+      given(250).expect('yellow')
+      given(400).expect('orange')
+      given(800).expect('red')
+    })
+  })
 
   test(letterScore, () => {
-    given('A').expect('brightgreen');
-    given('B').expect('green');
-    given('C').expect('yellowgreen');
-    given('D').expect('yellow');
-    given('E').expect('orange');
-    given('F').expect('red');
-    given('Z').expect('red');
-  });
+    given('A').expect('brightgreen')
+    given('B').expect('green')
+    given('C').expect('yellowgreen')
+    given('D').expect('yellow')
+    given('E').expect('orange')
+    given('F').expect('red')
+    given('Z').expect('red')
+  })
 
   const monthsAgo = months => {
-    const result = new Date();
+    const result = new Date()
     // This looks wack but it works.
-    result.setMonth(result.getMonth() - months);
-    return result;
-  };
+    result.setMonth(result.getMonth() - months)
+    return result
+  }
   test(age, () => {
-    given(Date.now()).describe('when given the current timestamp').expect('brightgreen');
-    given(new Date()).describe('when given the current Date').expect('brightgreen');
-    given(new Date(2001, 1, 1)).describe('when given a Date many years ago').expect('red');
-    given(monthsAgo(2)).describe('when given a Date two months ago').expect('yellowgreen');
-    given(monthsAgo(15)).describe('when given a Date 15 months ago').expect('orange');
-  });
+    given(Date.now())
+      .describe('when given the current timestamp')
+      .expect('brightgreen')
+    given(new Date())
+      .describe('when given the current Date')
+      .expect('brightgreen')
+    given(new Date(2001, 1, 1))
+      .describe('when given a Date many years ago')
+      .expect('red')
+    given(monthsAgo(2))
+      .describe('when given a Date two months ago')
+      .expect('yellowgreen')
+    given(monthsAgo(15))
+      .describe('when given a Date 15 months ago')
+      .expect('orange')
+  })
 
   test(version, () => {
-    forCases([
-      given('1.0'),
-      given(9),
-      given(1.0),
-    ]).expect('blue');
+    forCases([given('1.0'), given(9), given(1.0)]).expect('blue')
 
     forCases([
       given(0.1),
@@ -81,11 +89,23 @@ describe('Color formatters', function() {
       given('6.0-SNAPSHOT'),
       given('1.0.1-dev'),
       given('2.1.6-prerelease'),
-    ]).expect('orange');
+    ]).expect('orange')
 
-    expect(() => version(null)).to.throw(Error, "Can't generate a version color for null");
-    expect(() => version(undefined)).to.throw(Error, "Can't generate a version color for undefined");
-    expect(() => version(true)).to.throw(Error, "Can't generate a version color for true");
-    expect(() => version({})).to.throw(Error, "Can't generate a version color for [object Object]");
-  });
-});
+    expect(() => version(null)).to.throw(
+      Error,
+      "Can't generate a version color for null"
+    )
+    expect(() => version(undefined)).to.throw(
+      Error,
+      "Can't generate a version color for undefined"
+    )
+    expect(() => version(true)).to.throw(
+      Error,
+      "Can't generate a version color for true"
+    )
+    expect(() => version({})).to.throw(
+      Error,
+      "Can't generate a version color for [object Object]"
+    )
+  })
+})
diff --git a/lib/defaults.js b/lib/defaults.js
index 2dbf2b1e9c30c3e58046c468d62f31f950410cc6..5f7f7a1c37ebd2b03832ca0ae7be258bce63d821 100644
--- a/lib/defaults.js
+++ b/lib/defaults.js
@@ -1,10 +1,10 @@
-'use strict';
+'use strict'
 
-const path = require('path');
+const path = require('path')
 
 module.exports = {
   font: {
     // i.e. Verdana.ttf in the root of the project.
     path: path.join(__dirname, '..', 'Verdana.ttf'),
   },
-};
+}
diff --git a/lib/deprecated-services.js b/lib/deprecated-services.js
index 1fee40f48b452ba6e782850e6d28f55c731c37ea..31e818feb736599d67a23d8a8b886c8145a108cc 100644
--- a/lib/deprecated-services.js
+++ b/lib/deprecated-services.js
@@ -1,17 +1,17 @@
-'use strict';
+'use strict'
 
 const deprecatedServices = {
-  'gittip': new Date('2017-12-29'),
-  'gratipay': new Date('2017-12-29'),
-  'gemnasium': new Date('2018-05-15'),
-  'snap': new Date('2018-01-23'),
+  gittip: new Date('2017-12-29'),
+  gratipay: new Date('2017-12-29'),
+  gemnasium: new Date('2018-05-15'),
+  snap: new Date('2018-01-23'),
   'snap-ci': new Date('2018-01-23'),
-  'cauditor': new Date('2018-02-15'),
-  'dotnetstatus': new Date('2018-04-01'),
-  'magnumci': new Date('2018-07-08'),
-  'bithound': new Date('2018-07-08'),
-};
+  cauditor: new Date('2018-02-15'),
+  dotnetstatus: new Date('2018-04-01'),
+  magnumci: new Date('2018-07-08'),
+  bithound: new Date('2018-07-08'),
+}
 
 module.exports = {
-  deprecatedServices
+  deprecatedServices,
 }
diff --git a/lib/deprecation-helpers.js b/lib/deprecation-helpers.js
index 6473db75a27bc6773e8e34ec1bd7cfc1f0326ba2..c9f26194c4f178253aefde4f8a2f028b7591dc09 100644
--- a/lib/deprecation-helpers.js
+++ b/lib/deprecation-helpers.js
@@ -1,23 +1,27 @@
-'use strict';
+'use strict'
 
-const { makeBadgeData, setBadgeColor } = require('./badge-data');
-const { deprecatedServices } = require('./deprecated-services');
+const { makeBadgeData, setBadgeColor } = require('./badge-data')
+const { deprecatedServices } = require('./deprecated-services')
 
-const isDeprecated = function (service, now=new Date(), depServices=deprecatedServices) {
+const isDeprecated = function(
+  service,
+  now = new Date(),
+  depServices = deprecatedServices
+) {
   if (!(service in depServices)) {
-    return false;
+    return false
   }
-  return now.getTime() >= depServices[service].getTime();
-};
+  return now.getTime() >= depServices[service].getTime()
+}
 
-const getDeprecatedBadge = function (label, data) {
-  const badgeData = makeBadgeData(label, data);
-  setBadgeColor(badgeData, 'lightgray');
-  badgeData.text[1] = 'no longer available';
-  return badgeData;
-};
+const getDeprecatedBadge = function(label, data) {
+  const badgeData = makeBadgeData(label, data)
+  setBadgeColor(badgeData, 'lightgray')
+  badgeData.text[1] = 'no longer available'
+  return badgeData
+}
 
 module.exports = {
   isDeprecated,
   getDeprecatedBadge,
-};
+}
diff --git a/lib/deprecation-helpers.spec.js b/lib/deprecation-helpers.spec.js
index 25fb207f0d05fff927c177f457afa2760cf80d3d..867231d61c2f3242055a5260f2ea3fdaa3a69e83 100644
--- a/lib/deprecation-helpers.spec.js
+++ b/lib/deprecation-helpers.spec.js
@@ -1,39 +1,33 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const { test, given } = require('sazerac');
-const { isDeprecated, getDeprecatedBadge } = require('./deprecation-helpers');
+const { expect } = require('chai')
+const { test, given } = require('sazerac')
+const { isDeprecated, getDeprecatedBadge } = require('./deprecation-helpers')
 
 describe('Deprecated Badge Helper', function() {
   it('makes "no longer available" badge', function() {
-    const badge = getDeprecatedBadge('foo', {});
-    expect(badge.text[0]).to.equal('foo');
-    expect(badge.text[1]).to.equal('no longer available');
-    expect(badge.colorscheme).to.equal('lightgray');
-  });
+    const badge = getDeprecatedBadge('foo', {})
+    expect(badge.text[0]).to.equal('foo')
+    expect(badge.text[1]).to.equal('no longer available')
+    expect(badge.colorscheme).to.equal('lightgray')
+  })
 
   it('ignores colorB param', function() {
-    const badge = getDeprecatedBadge('foo', {colorB: 'fedcba'});
-    expect(badge.colorscheme).to.equal('lightgray');
-  });
-});
-
-describe('isDeprecated function', function () {
-  test(isDeprecated, function () {
-
-    given('fooservice', new Date(), {}).expect(false);
-
-    given(
-      'fooservice',
-      new Date('2001-01-11 23:59:00Z'),
-      {'fooservice': new Date('2001-01-12')}
-    ).expect(false);
-
-    given(
-      'fooservice',
-      new Date('2001-01-12 00:00:01Z'),
-      {'fooservice': new Date('2001-01-12')}
-    ).expect(true);
-
-  });
-});
+    const badge = getDeprecatedBadge('foo', { colorB: 'fedcba' })
+    expect(badge.colorscheme).to.equal('lightgray')
+  })
+})
+
+describe('isDeprecated function', function() {
+  test(isDeprecated, function() {
+    given('fooservice', new Date(), {}).expect(false)
+
+    given('fooservice', new Date('2001-01-11 23:59:00Z'), {
+      fooservice: new Date('2001-01-12'),
+    }).expect(false)
+
+    given('fooservice', new Date('2001-01-12 00:00:01Z'), {
+      fooservice: new Date('2001-01-12'),
+    }).expect(true)
+  })
+})
diff --git a/lib/error-helper.js b/lib/error-helper.js
index cc4b3786ea2351479e1f1316eeafd03f19de136e..0fed84ae322cf1f1c7a22dc358b8865a7dc752fb 100644
--- a/lib/error-helper.js
+++ b/lib/error-helper.js
@@ -1,52 +1,56 @@
-'use strict';
+'use strict'
 
-const {
-  NotFound,
-  InvalidResponse,
-} = require('../services/errors');
+const { NotFound, InvalidResponse } = require('../services/errors')
 
-const checkErrorResponse = function(badgeData, err, res, notFoundMessage = 'not found') {
+const checkErrorResponse = function(
+  badgeData,
+  err,
+  res,
+  notFoundMessage = 'not found'
+) {
   if (err != null) {
-    badgeData.text[1] = 'inaccessible';
-    badgeData.colorscheme = 'red';
-    return true;
+    badgeData.text[1] = 'inaccessible'
+    badgeData.colorscheme = 'red'
+    return true
   } else if (res.statusCode === 404) {
-    badgeData.text[1] = notFoundMessage;
-    badgeData.colorscheme = 'lightgrey';
-    return true;
+    badgeData.text[1] = notFoundMessage
+    badgeData.colorscheme = 'lightgrey'
+    return true
   } else if (res.statusCode !== 200) {
-    badgeData.text[1] = 'invalid';
-    badgeData.colorscheme = 'lightgrey';
-    return true;
+    badgeData.text[1] = 'invalid'
+    badgeData.colorscheme = 'lightgrey'
+    return true
   } else {
-    return false;
+    return false
   }
-};
+}
 
-checkErrorResponse.asPromise = function ({ notFoundMessage } = {}) {
-  return async function ({ buffer, res }) {
+checkErrorResponse.asPromise = function({ notFoundMessage } = {}) {
+  return async function({ buffer, res }) {
     if (res.statusCode === 404) {
-      throw new NotFound({ prettyMessage: notFoundMessage });
+      throw new NotFound({ prettyMessage: notFoundMessage })
     } else if (res.statusCode !== 200) {
-      const underlying = Error(`Got status code ${res.statusCode} (expected 200)`);
-      throw new InvalidResponse({ underlyingError: underlying});
+      const underlying = Error(
+        `Got status code ${res.statusCode} (expected 200)`
+      )
+      throw new InvalidResponse({ underlyingError: underlying })
     }
-    return { buffer, res };
-  };
-};
+    return { buffer, res }
+  }
+}
 
 async function asJson({ buffer, res }) {
   try {
-    return JSON.parse(buffer);
+    return JSON.parse(buffer)
   } catch (err) {
     throw new InvalidResponse({
       prettyMessage: 'unparseable json response',
       underlyingError: err,
-    });
+    })
   }
 }
 
 module.exports = {
   checkErrorResponse,
   asJson,
-};
+}
diff --git a/lib/error-helper.spec.js b/lib/error-helper.spec.js
index b3c4c3e4642ed7576c6c1927e79f18ad231bc98f..35729f06df695eeadabb9d96a5e85dd73a1df62d 100644
--- a/lib/error-helper.spec.js
+++ b/lib/error-helper.spec.js
@@ -1,95 +1,105 @@
-'use strict';
+'use strict'
 
-const chai = require('chai');
-const { assert, expect } = chai;
-const { checkErrorResponse } = require('./error-helper');
-const { NotFound, InvalidResponse } = require('../services/errors');
+const chai = require('chai')
+const { assert, expect } = chai
+const { checkErrorResponse } = require('./error-helper')
+const { NotFound, InvalidResponse } = require('../services/errors')
 
-chai.use(require('chai-as-promised'));
+chai.use(require('chai-as-promised'))
 
 describe('Standard Error Handler', function() {
   it('makes inaccessible badge', function() {
-    const badgeData = {'text': []};
-    assert.equal(true, checkErrorResponse(badgeData, 'something other than null', {}));
-    assert.equal('inaccessible', badgeData.text[1]);
-    assert.equal('red', badgeData.colorscheme);
-  });
+    const badgeData = { text: [] }
+    assert.equal(
+      true,
+      checkErrorResponse(badgeData, 'something other than null', {})
+    )
+    assert.equal('inaccessible', badgeData.text[1])
+    assert.equal('red', badgeData.colorscheme)
+  })
 
   it('makes not found badge', function() {
-    const badgeData = {'text': []};
-    assert.equal(true, checkErrorResponse(badgeData, null, {statusCode: 404}));
-    assert.equal('not found', badgeData.text[1]);
-    assert.equal('lightgrey', badgeData.colorscheme);
-  });
+    const badgeData = { text: [] }
+    assert.equal(true, checkErrorResponse(badgeData, null, { statusCode: 404 }))
+    assert.equal('not found', badgeData.text[1])
+    assert.equal('lightgrey', badgeData.colorscheme)
+  })
 
   it('makes not found badge with custom error', function() {
-    const badgeData = {'text': []};
-    assert.equal(true, checkErrorResponse(badgeData, null, {statusCode: 404}, 'custom message'));
-    assert.equal('custom message', badgeData.text[1]);
-    assert.equal('lightgrey', badgeData.colorscheme);
-  });
+    const badgeData = { text: [] }
+    assert.equal(
+      true,
+      checkErrorResponse(badgeData, null, { statusCode: 404 }, 'custom message')
+    )
+    assert.equal('custom message', badgeData.text[1])
+    assert.equal('lightgrey', badgeData.colorscheme)
+  })
 
   it('makes invalid badge', function() {
-    const badgeData = {'text': []};
-    assert.equal(true, checkErrorResponse(badgeData, null, {statusCode: 500}));
-    assert.equal('invalid', badgeData.text[1]);
-    assert.equal('lightgrey', badgeData.colorscheme);
-  });
+    const badgeData = { text: [] }
+    assert.equal(true, checkErrorResponse(badgeData, null, { statusCode: 500 }))
+    assert.equal('invalid', badgeData.text[1])
+    assert.equal('lightgrey', badgeData.colorscheme)
+  })
 
   it('return false on 200 status', function() {
-    assert.equal(false, checkErrorResponse({'text': []}, null, {statusCode: 200}));
-  });
-});
+    assert.equal(
+      false,
+      checkErrorResponse({ text: [] }, null, { statusCode: 200 })
+    )
+  })
+})
 
 describe('async error handler', function() {
   context('when status is 200', function() {
     it('passes through the inputs', async function() {
-      const args = { buffer: 'buffer', res: { statusCode: 200 } };
-      expect(await checkErrorResponse.asPromise()(args))
-        .to.deep.equal(args);
-    });
-  });
+      const args = { buffer: 'buffer', res: { statusCode: 200 } }
+      expect(await checkErrorResponse.asPromise()(args)).to.deep.equal(args)
+    })
+  })
 
   context('when status is 404', function() {
-    const res = { statusCode: 404 };
+    const res = { statusCode: 404 }
 
     it('throws NotFound', async function() {
       try {
-        await checkErrorResponse.asPromise()({ res });
-        expect.fail('Expected to throw');
+        await checkErrorResponse.asPromise()({ res })
+        expect.fail('Expected to throw')
       } catch (e) {
-        expect(e).to.be.an.instanceof(NotFound);
-        expect(e.message).to.equal('Not Found');
-        expect(e.prettyMessage).to.equal('not found');
+        expect(e).to.be.an.instanceof(NotFound)
+        expect(e.message).to.equal('Not Found')
+        expect(e.prettyMessage).to.equal('not found')
       }
-    });
+    })
 
     it('displays the custom not found message', async function() {
-      const notFoundMessage = 'no goblins found';
-      const res = { statusCode: 404 };
+      const notFoundMessage = 'no goblins found'
+      const res = { statusCode: 404 }
       try {
-        await checkErrorResponse.asPromise({ notFoundMessage })({ res });
-        expect.fail('Expected to throw');
+        await checkErrorResponse.asPromise({ notFoundMessage })({ res })
+        expect.fail('Expected to throw')
       } catch (e) {
-        expect(e).to.be.an.instanceof(NotFound);
-        expect(e.message).to.equal('Not Found: no goblins found');
-        expect(e.prettyMessage).to.equal('no goblins found');
+        expect(e).to.be.an.instanceof(NotFound)
+        expect(e.message).to.equal('Not Found: no goblins found')
+        expect(e.prettyMessage).to.equal('no goblins found')
       }
-    });
-  });
+    })
+  })
 
   context('when status is 500', function() {
-    const res = { statusCode: 500 };
+    const res = { statusCode: 500 }
 
     it('throws InvalidResponse', async function() {
       try {
-        await checkErrorResponse.asPromise()({ res });
-        expect.fail('Expected to throw');
+        await checkErrorResponse.asPromise()({ res })
+        expect.fail('Expected to throw')
       } catch (e) {
-        expect(e).to.be.an.instanceof(InvalidResponse);
-        expect(e.message).to.equal('Invalid Response: Got status code 500 (expected 200)');
-        expect(e.prettyMessage).to.equal('invalid');
+        expect(e).to.be.an.instanceof(InvalidResponse)
+        expect(e.message).to.equal(
+          'Invalid Response: Got status code 500 (expected 200)'
+        )
+        expect(e.prettyMessage).to.equal('invalid')
       }
-    });
-  });
-});
+    })
+  })
+})
diff --git a/lib/export-badge-examples-cli.js b/lib/export-badge-examples-cli.js
index 230059f32c3a9834ddf884ed871c05949a2d3608..ab1ba8eb49b02a1529696dd4708cf5d7ede373c2 100644
--- a/lib/export-badge-examples-cli.js
+++ b/lib/export-badge-examples-cli.js
@@ -1,5 +1,5 @@
-'use strict';
+'use strict'
 
-const allBadgeExamples = require('./all-badge-examples');
+const allBadgeExamples = require('./all-badge-examples')
 
-process.stdout.write(JSON.stringify(allBadgeExamples));
+process.stdout.write(JSON.stringify(allBadgeExamples))
diff --git a/lib/export-supported-features-cli.js b/lib/export-supported-features-cli.js
index 7757412239738955ff7e0ca0de5fad503ef135b0..19fd67d5276729ae8622b39bda9d1dc3f927b83e 100644
--- a/lib/export-supported-features-cli.js
+++ b/lib/export-supported-features-cli.js
@@ -1,7 +1,7 @@
-'use strict';
+'use strict'
 
-const path = require('path');
-const glob = require('glob');
+const path = require('path')
+const glob = require('glob')
 
 const supportedFeatures = {
   logos: glob
@@ -16,6 +16,6 @@ const supportedFeatures = {
     'popout-square',
     'social',
   ],
-};
+}
 
-console.log(JSON.stringify(supportedFeatures, null, 2));
+console.log(JSON.stringify(supportedFeatures, null, 2))
diff --git a/lib/github-auth.js b/lib/github-auth.js
index 9082c8122596a8b611f8f29fe2b064e27af3f0ee..24ccc5e07f70d759ef2cbbc7317935ef14e9215b 100644
--- a/lib/github-auth.js
+++ b/lib/github-auth.js
@@ -1,69 +1,83 @@
-'use strict';
+'use strict'
 
-const path = require('path');
-const crypto = require('crypto');
-const log = require('./log');
-const queryString = require('query-string');
-const request = require('request');
-const autosave = require('json-autosave');
-const serverSecrets = require('./server-secrets');
-const mapKeys = require('lodash.mapkeys');
+const path = require('path')
+const crypto = require('crypto')
+const log = require('./log')
+const queryString = require('query-string')
+const request = require('request')
+const autosave = require('json-autosave')
+const serverSecrets = require('./server-secrets')
+const mapKeys = require('lodash.mapkeys')
 
 // This is an initial value which makes the code work while the initial data
 // is loaded. In the then() callback of scheduleAutosaving(), it's reassigned
 // with a JsonSave object.
-let githubUserTokens = {data: []};
+let githubUserTokens = { data: [] }
 
 function scheduleAutosaving(config) {
-  const { dir: persistenceDir } = config;
-  const githubUserTokensFile = path.resolve(persistenceDir, 'github-user-tokens.json');
-  autosave(githubUserTokensFile, {data: []}).then(save => {
-    githubUserTokens = save;
-    for (let i = 0; i < githubUserTokens.data.length; i++) {
-      addGithubToken(githubUserTokens.data[i]);
-    }
-    // Personal tokens allow access to GitHub private repositories.
-    // You can manage your personal GitHub token at
-    // <https://github.com/settings/tokens>.
-    if (serverSecrets && serverSecrets.gh_token) {
-      addGithubToken(serverSecrets.gh_token);
-    }
-  }).catch(e => {
-    console.error('Could not create ' + githubUserTokensFile);
-  });
+  const { dir: persistenceDir } = config
+  const githubUserTokensFile = path.resolve(
+    persistenceDir,
+    'github-user-tokens.json'
+  )
+  autosave(githubUserTokensFile, { data: [] })
+    .then(save => {
+      githubUserTokens = save
+      for (let i = 0; i < githubUserTokens.data.length; i++) {
+        addGithubToken(githubUserTokens.data[i])
+      }
+      // Personal tokens allow access to GitHub private repositories.
+      // You can manage your personal GitHub token at
+      // <https://github.com/settings/tokens>.
+      if (serverSecrets && serverSecrets.gh_token) {
+        addGithubToken(serverSecrets.gh_token)
+      }
+    })
+    .catch(e => {
+      console.error('Could not create ' + githubUserTokensFile)
+    })
 }
 
 function cancelAutosaving() {
   if (githubUserTokens.stop) {
-    githubUserTokens.stop();
-    githubUserTokens.save();
-    githubUserTokens = {data: []};
+    githubUserTokens.stop()
+    githubUserTokens.save()
+    githubUserTokens = { data: [] }
   }
 }
 
 function setRoutes(server) {
-  const baseUrl = process.env.BASE_URL || 'https://img.shields.io';
+  const baseUrl = process.env.BASE_URL || 'https://img.shields.io'
 
   server.route(/^\/github-auth$/, function(data, match, end, ask) {
     if (!(serverSecrets && serverSecrets.gh_client_id)) {
-      return end('This server is missing GitHub client secrets.');
+      return end('This server is missing GitHub client secrets.')
     }
     const query = queryString.stringify({
       client_id: serverSecrets.gh_client_id,
       redirect_uri: baseUrl + '/github-auth/done',
-    });
-    ask.res.statusCode = 302;  // Found.
-    ask.res.setHeader('Location', 'https://github.com/login/oauth/authorize?' + query);
-    end('');
-  });
+    })
+    ask.res.statusCode = 302 // Found.
+    ask.res.setHeader(
+      'Location',
+      'https://github.com/login/oauth/authorize?' + query
+    )
+    end('')
+  })
 
   server.route(/^\/github-auth\/done$/, function(data, match, end, ask) {
-    if (!(serverSecrets && serverSecrets.gh_client_id && serverSecrets.gh_client_secret)) {
-      return end('This server is missing GitHub client secrets.');
+    if (
+      !(
+        serverSecrets &&
+        serverSecrets.gh_client_id &&
+        serverSecrets.gh_client_secret
+      )
+    ) {
+      return end('This server is missing GitHub client secrets.')
     }
     if (!data.code) {
-      log(`GitHub OAuth data.code: ${JSON.stringify(data)}`);
-      return end('GitHub OAuth authentication failed to provide a code.');
+      log(`GitHub OAuth data.code: ${JSON.stringify(data)}`)
+      return end('GitHub OAuth authentication failed to provide a code.')
     }
     const options = {
       url: 'https://github.com/login/oauth/access_token',
@@ -77,20 +91,25 @@ function setRoutes(server) {
         code: data.code,
       }),
       method: 'POST',
-    };
+    }
     request(options, function(err, res, body) {
-      if (err != null) { return end('The connection to GitHub failed.'); }
-      let content;
+      if (err != null) {
+        return end('The connection to GitHub failed.')
+      }
+      let content
       try {
-        content = queryString.parse(body);
-      } catch(e) { return end('The GitHub OAuth token could not be parsed.'); }
-      const token = content.access_token;
+        content = queryString.parse(body)
+      } catch (e) {
+        return end('The GitHub OAuth token could not be parsed.')
+      }
+      const token = content.access_token
       if (!token) {
-        return end('The GitHub OAuth process did not return a user token.');
+        return end('The GitHub OAuth process did not return a user token.')
       }
 
-      ask.res.setHeader('Content-Type', 'text/html');
-      end('<p>Shields.io has received your app-specific GitHub user token. ' +
+      ask.res.setHeader('Content-Type', 'text/html')
+      end(
+        '<p>Shields.io has received your app-specific GitHub user token. ' +
           'You can revoke it by going to ' +
           '<a href="https://github.com/settings/applications">GitHub</a>.</p>' +
           '<p>Until you do, you have now increased the rate limit for GitHub ' +
@@ -98,97 +117,105 @@ function setRoutes(server) {
           'therefore more robust.</p>' +
           '<p>Thanks for contributing to a smoother experience for ' +
           'everyone!</p>' +
-          '<p><a href="/">Back to the website</a></p>');
+          '<p><a href="/">Back to the website</a></p>'
+      )
 
-      sendTokenToAllServers(token)
-      .catch(function(e) {
-        console.error('GitHub user token transmission failed:', e);
-      });
-    });
-  });
+      sendTokenToAllServers(token).catch(function(e) {
+        console.error('GitHub user token transmission failed:', e)
+      })
+    })
+  })
 
   server.route(/^\/github-auth\/add-token$/, function(data, match, end, ask) {
-    if (!crypto.timingSafeEqual(data.shieldsSecret, serverSecrets.shieldsSecret)) {
+    if (
+      !crypto.timingSafeEqual(data.shieldsSecret, serverSecrets.shieldsSecret)
+    ) {
       // An unknown entity tries to connect. Let the connection linger for 10s.
-      return setTimeout(function() { end('Invalid secret.'); }, 10000);
+      return setTimeout(function() {
+        end('Invalid secret.')
+      }, 10000)
     }
-    addGithubToken(data.token);
-    end('Thanks!');
-  });
+    addGithubToken(data.token)
+    end('Thanks!')
+  })
 }
 
 function sendTokenToAllServers(token) {
-  const ips = serverSecrets.shieldsIps;
-  return Promise.all(ips.map(function(ip) {
-    return new Promise(function(resolve, reject) {
-      const options = {
-        url: 'https://' + ip + '/github-auth/add-token',
-        method: 'POST',
-        form: {
-          shieldsSecret: serverSecrets.shieldsSecret,
-          token: token,
-        },
-        // We target servers by IP, and we use HTTPS. Assuming that
-        // 1. Internet routers aren't hacked, and
-        // 2. We don't unknowingly lose our IP to someone else,
-        // we're not leaking people's and our information.
-        // (If we did, it would have no impact, as we only ask for a token,
-        // no GitHub scope. The malicious entity would only be able to use
-        // our rate limit pool.)
-        // FIXME: use letsencrypt.
-        strictSSL: false,
-      };
-      request(options, function(err, res, body) {
-        if (err != null) { return reject(err); }
-        resolve();
-      });
-    });
-  }));
+  const ips = serverSecrets.shieldsIps
+  return Promise.all(
+    ips.map(function(ip) {
+      return new Promise(function(resolve, reject) {
+        const options = {
+          url: 'https://' + ip + '/github-auth/add-token',
+          method: 'POST',
+          form: {
+            shieldsSecret: serverSecrets.shieldsSecret,
+            token: token,
+          },
+          // We target servers by IP, and we use HTTPS. Assuming that
+          // 1. Internet routers aren't hacked, and
+          // 2. We don't unknowingly lose our IP to someone else,
+          // we're not leaking people's and our information.
+          // (If we did, it would have no impact, as we only ask for a token,
+          // no GitHub scope. The malicious entity would only be able to use
+          // our rate limit pool.)
+          // FIXME: use letsencrypt.
+          strictSSL: false,
+        }
+        request(options, function(err, res, body) {
+          if (err != null) {
+            return reject(err)
+          }
+          resolve()
+        })
+      })
+    })
+  )
 }
 
 // Track rate limit requests remaining.
 
 // Ideally, we would want priority queues here.
-const reqRemaining = new Map();  // From token to requests remaining.
-const reqReset = new Map();  // From token to timestamp.
+const reqRemaining = new Map() // From token to requests remaining.
+const reqReset = new Map() // From token to timestamp.
 
 // token: client token as a string.
 // reqs: number of requests remaining.
 // reset: timestamp when the number of remaining requests is reset.
 function setReqRemaining(token, reqs, reset) {
-  reqRemaining.set(token, reqs);
-  reqReset.set(token, reset);
+  reqRemaining.set(token, reqs)
+  reqReset.set(token, reset)
 }
 
 function rmReqRemaining(token) {
-  reqRemaining.delete(token);
-  reqReset.delete(token);
+  reqRemaining.delete(token)
+  reqReset.delete(token)
 }
 
 function utcEpochSeconds() {
-  return ((Date.now() / 1000) >>> 0);
+  return (Date.now() / 1000) >>> 0
 }
 
-const userTokenRateLimit = 12500;
+const userTokenRateLimit = 12500
 
 // Return false if the token cannot reasonably be expected to perform
 // a GitHub request.
 function isTokenUsable(token, now) {
-  const reqs = reqRemaining.get(token);
-  const reset = reqReset.get(token);
+  const reqs = reqRemaining.get(token)
+  const reset = reqReset.get(token)
   // We don't want to empty more than 3/4 of a user's rate limit.
-  const hasRemainingReqs = reqs > (userTokenRateLimit / 4);
-  const isBeyondRateLimitReset = reset < now;
-  return hasRemainingReqs || isBeyondRateLimitReset;
+  const hasRemainingReqs = reqs > userTokenRateLimit / 4
+  const isBeyondRateLimitReset = reset < now
+  return hasRemainingReqs || isBeyondRateLimitReset
 }
 
 // Return a list of tokens (as strings) which can be used for a GitHub request,
 // with a reasonable chance that the request will succeed.
 function usableTokens() {
-  const now = utcEpochSeconds();
+  const now = utcEpochSeconds()
   return githubUserTokens.data.filter(function(token) {
-    return isTokenUsable(token, now);
-  });
+    return isTokenUsable(token, now)
+  })
 }
 
 // Retrieve a user token if there is one for which we believe there are requests
@@ -197,57 +224,58 @@ function getReqRemainingToken() {
   // Go through the user tokens.
   // Among usable ones, use the one with the highest number of remaining
   // requests.
-  const tokens = usableTokens();
-  let highestReq = -1;
-  let highestToken;
+  const tokens = usableTokens()
+  let highestReq = -1
+  let highestToken
   for (let i = 0; i < tokens.length; i++) {
-    const token = tokens[i];
-    const reqs = reqRemaining.get(token);
+    const token = tokens[i]
+    const reqs = reqRemaining.get(token)
     if (reqs > highestReq) {
-      highestReq = reqs;
-      highestToken = token;
+      highestReq = reqs
+      highestToken = token
     }
   }
-  return highestToken;
+  return highestToken
 }
 
 function addGithubToken(token) {
   // A reset date of 0 has to be in the past.
-  setReqRemaining(token, userTokenRateLimit, 0);
+  setReqRemaining(token, userTokenRateLimit, 0)
   // Insert it only if it is not registered yet.
   if (githubUserTokens.data.indexOf(token) === -1) {
-    githubUserTokens.data.push(token);
+    githubUserTokens.data.push(token)
   }
 }
 
 function rmGithubToken(token) {
-  rmReqRemaining(token);
+  rmReqRemaining(token)
   // Remove it only if it is in there.
-  const idx = githubUserTokens.data.indexOf(token);
+  const idx = githubUserTokens.data.indexOf(token)
   if (idx >= 0) {
-    githubUserTokens.data.splice(idx, 1);
+    githubUserTokens.data.splice(idx, 1)
   }
 }
 
 // Convert an ES6 Map to an object.
 function mapToObject(map) {
-  const result = {};
+  const result = {}
   for (const [k, v] of map) {
-    result[k] = v;
+    result[k] = v
   }
-  return result;
+  return result
 }
 
 // Compute a one-way hash of the input string.
 function sha(str) {
-  return crypto.createHash('sha256')
+  return crypto
+    .createHash('sha256')
     .update(str, 'utf-8')
-    .digest('hex');
+    .digest('hex')
 }
 
 function serializeDebugInfo(options) {
   // Apply defaults.
-  const { sanitize } = Object.assign({ sanitize: true }, options);
+  const { sanitize } = Object.assign({ sanitize: true }, options)
 
   const unsanitized = {
     tokens: githubUserTokens.data,
@@ -255,7 +283,7 @@ function serializeDebugInfo(options) {
     reqReset: mapToObject(reqReset),
     utcEpochSeconds: utcEpochSeconds(),
     sanitized: false,
-  };
+  }
 
   if (sanitize) {
     return {
@@ -264,9 +292,9 @@ function serializeDebugInfo(options) {
       reqReset: mapKeys(unsanitized.reqReset, (v, k) => sha(k)),
       utcEpochSeconds: unsanitized.utcEpochSeconds,
       sanitized: true,
-    };
+    }
   } else {
-    return unsanitized;
+    return unsanitized
   }
 }
 
@@ -275,48 +303,54 @@ function serializeDebugInfo(options) {
 // is provided, and more predictable failures if that token is exhausted.
 //
 // You can manage your personal GitHub token at https://github.com/settings/tokens
-const globalToken = (serverSecrets || {}).gh_token;
+const globalToken = (serverSecrets || {}).gh_token
 
 // Act like request(), but tweak headers and query to avoid hitting a rate
 // limit.
 function githubRequest(request, url, query, cb) {
-  query = query || {};
+  query = query || {}
   // A special User-Agent is required:
   // http://developer.github.com/v3/#user-agent-required
   const headers = {
     'User-Agent': 'Shields.io',
-    'Accept': 'application/vnd.github.v3+json',
-  };
+    Accept: 'application/vnd.github.v3+json',
+  }
 
-  const githubToken = globalToken === undefined ? getReqRemainingToken() : globalToken;
+  const githubToken =
+    globalToken === undefined ? getReqRemainingToken() : globalToken
 
   if (githubToken != null) {
     // Typically, GitHub user tokens grants us 12500 req/hour.
-    headers['Authorization'] = 'token ' + githubToken;
+    headers['Authorization'] = 'token ' + githubToken
   } else if (serverSecrets && serverSecrets.gh_client_id) {
     // Using our OAuth App secret grants us 5000 req/hour
     // instead of the standard 60 req/hour.
-    query.client_id = serverSecrets.gh_client_id;
-    query.client_secret = serverSecrets.gh_client_secret;
+    query.client_id = serverSecrets.gh_client_id
+    query.client_secret = serverSecrets.gh_client_secret
   }
 
-  const qs = queryString.stringify(query);
-  if (qs) { url += '?' + qs; }
+  const qs = queryString.stringify(query)
+  if (qs) {
+    url += '?' + qs
+  }
 
-  request(url, {headers: headers}, function(err, res, buffer) {
+  request(url, { headers: headers }, function(err, res, buffer) {
     if (globalToken !== null && githubToken !== null && err === null) {
-      if (res.statusCode === 401) {  // Unauthorized.
-        rmGithubToken(githubToken);
+      if (res.statusCode === 401) {
+        // Unauthorized.
+        rmGithubToken(githubToken)
       } else {
-        const remaining = +res.headers['x-ratelimit-remaining'];
+        const remaining = +res.headers['x-ratelimit-remaining']
         // reset is in UTC epoch seconds.
-        const reset = +res.headers['x-ratelimit-reset'];
-        setReqRemaining(githubToken, remaining, reset);
-        if (remaining === 0) { return; }  // Hope for the best in the cache.
+        const reset = +res.headers['x-ratelimit-reset']
+        setReqRemaining(githubToken, remaining, reset)
+        if (remaining === 0) {
+          return
+        } // Hope for the best in the cache.
       }
     }
-    cb(err, res, buffer);
-  });
+    cb(err, res, buffer)
+  })
 }
 
 module.exports = {
@@ -325,4 +359,4 @@ module.exports = {
   request: githubRequest,
   setRoutes,
   serializeDebugInfo,
-};
+}
diff --git a/lib/github-auth/is-valid-token.js b/lib/github-auth/is-valid-token.js
index 6de42568a75ad11dd35d3a8685819bd121600aee..bfb8b7f018fbf58df33b9fdff4f6e7cb3c8006da 100644
--- a/lib/github-auth/is-valid-token.js
+++ b/lib/github-auth/is-valid-token.js
@@ -1,8 +1,8 @@
-'use strict';
+'use strict'
 
 // This is only used by the TokenProviders, though probably the acceptor
 // should use it too.
 
-const isValidToken = t => /^[0-9a-f]{40}$/.test(t);
+const isValidToken = t => /^[0-9a-f]{40}$/.test(t)
 
-module.exports = isValidToken;
+module.exports = isValidToken
diff --git a/lib/github-helpers.js b/lib/github-helpers.js
index 918b59ebfdf508036c88ca34fbbe2b405371feab..aef5a6cb3a5e8e991d09a630c39f8258f470df59 100644
--- a/lib/github-helpers.js
+++ b/lib/github-helpers.js
@@ -1,30 +1,42 @@
-'use strict';
+'use strict'
 
-const { colorScale } = require('./color-formatters');
-const { checkErrorResponse: standardCheckErrorResponse } = require('./error-helper');
+const { colorScale } = require('./color-formatters')
+const {
+  checkErrorResponse: standardCheckErrorResponse,
+} = require('./error-helper')
 
 function stateColor(s) {
-  return { open: '2cbe4e', closed: 'cb2431', merged: '6f42c1' }[s];
+  return { open: '2cbe4e', closed: 'cb2431', merged: '6f42c1' }[s]
 }
 
 function checkStateColor(s) {
-  return { pending: 'dbab09', success: '2cbe4e', failure: 'cb2431', error: 'cb2431' }[s];
+  return {
+    pending: 'dbab09',
+    success: '2cbe4e',
+    failure: 'cb2431',
+    error: 'cb2431',
+  }[s]
 }
 
-function checkErrorResponse(badgeData, err, res, notFoundMessage = 'repo not found') {
+function checkErrorResponse(
+  badgeData,
+  err,
+  res,
+  notFoundMessage = 'repo not found'
+) {
   if (res && res.statusCode === 422) {
-    badgeData.text[1] = notFoundMessage;
-    badgeData.colorscheme = 'lightgrey';
-    return true;
+    badgeData.text[1] = notFoundMessage
+    badgeData.colorscheme = 'lightgrey'
+    return true
   }
-  return standardCheckErrorResponse(badgeData, err, res, notFoundMessage);
+  return standardCheckErrorResponse(badgeData, err, res, notFoundMessage)
 }
 
-const commentsColor = colorScale([1, 3, 10, 25], undefined, true);
+const commentsColor = colorScale([1, 3, 10, 25], undefined, true)
 
 module.exports = {
   stateColor,
   checkStateColor,
   commentsColor,
-  checkErrorResponse
-};
+  checkErrorResponse,
+}
diff --git a/lib/github-helpers.spec.js b/lib/github-helpers.spec.js
index cf06b8258e549dfabb64942fe7652e30248942db..079410ba41d098eb75a95d7816590d295fe4e39d 100644
--- a/lib/github-helpers.spec.js
+++ b/lib/github-helpers.spec.js
@@ -1,13 +1,15 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const { checkErrorResponse } = require('./github-helpers');
+const { expect } = require('chai')
+const { checkErrorResponse } = require('./github-helpers')
 
 describe('GitHub Error Handler', function() {
   it('makes not found badge when 422 is returned', function() {
-    const badgeData = {'text': []};
-    expect(checkErrorResponse(badgeData, null, {statusCode: 422}, 'repo not found')).to.be.true;
-    expect(badgeData.text[1]).to.equal('repo not found');
-    expect(badgeData.colorscheme).to.equal('lightgrey');
-  });
-});
+    const badgeData = { text: [] }
+    expect(
+      checkErrorResponse(badgeData, null, { statusCode: 422 }, 'repo not found')
+    ).to.be.true
+    expect(badgeData.text[1]).to.equal('repo not found')
+    expect(badgeData.colorscheme).to.equal('lightgrey')
+  })
+})
diff --git a/lib/github-provider.js b/lib/github-provider.js
index 5bade1b26d07aa24da174d9a4f840e428fadbe0f..b077f797d0ead8257c620629c4523881f0232caa 100644
--- a/lib/github-provider.js
+++ b/lib/github-provider.js
@@ -1,126 +1,124 @@
-'use strict';
-const moment = require('moment');
+'use strict'
+const moment = require('moment')
 
 const {
   makeBadgeData: getBadgeData,
   makeLabel: getLabel,
   makeLogo: getLogo,
-} = require('./badge-data');
-const {
-  formatDate
-} = require('./text-formatters');
+} = require('./badge-data')
+const { formatDate } = require('./text-formatters')
 
-const {
-  age
-} = require('./color-formatters');
+const { age } = require('./color-formatters')
 
 // GitHub commits since integration.
 function mapGithubCommitsSince({ camp, cache }, githubApiProvider) {
-  camp.route(/^\/github\/commits-since\/([^/]+)\/([^/]+)\/([^/]+)\.(svg|png|gif|jpg|json)$/,
-    cache(function (data, match, sendBadge, request) {
-      const user = match[1];  // eg, SubtitleEdit
-      const repo = match[2];  // eg, subtitleedit
-      const version = match[3];  // eg, 3.4.7 or latest
-      const format = match[4];
-      const badgeData = getBadgeData('commits since ' + version, data);
+  camp.route(
+    /^\/github\/commits-since\/([^/]+)\/([^/]+)\/([^/]+)\.(svg|png|gif|jpg|json)$/,
+    cache(function(data, match, sendBadge, request) {
+      const user = match[1] // eg, SubtitleEdit
+      const repo = match[2] // eg, subtitleedit
+      const version = match[3] // eg, 3.4.7 or latest
+      const format = match[4]
+      const badgeData = getBadgeData('commits since ' + version, data)
 
       function setCommitsSinceBadge(user, repo, version) {
-        const apiUrl = `/repos/${user}/${repo}/compare/${version}...master`;
+        const apiUrl = `/repos/${user}/${repo}/compare/${version}...master`
         if (badgeData.template === 'social') {
-          badgeData.logo = getLogo('github', data);
+          badgeData.logo = getLogo('github', data)
         }
         githubApiProvider.request(request, apiUrl, {}, (err, res, buffer) => {
           if (err != null) {
-            badgeData.text[1] = 'inaccessible';
-            sendBadge(format, badgeData);
-            return;
+            badgeData.text[1] = 'inaccessible'
+            sendBadge(format, badgeData)
+            return
           }
 
           try {
-            const result = JSON.parse(buffer);
-            badgeData.text[1] = result.ahead_by;
-            badgeData.colorscheme = 'blue';
-            badgeData.text[0] = getLabel('commits since ' + version, data);
-            sendBadge(format, badgeData);
-
+            const result = JSON.parse(buffer)
+            badgeData.text[1] = result.ahead_by
+            badgeData.colorscheme = 'blue'
+            badgeData.text[0] = getLabel('commits since ' + version, data)
+            sendBadge(format, badgeData)
           } catch (e) {
-            badgeData.text[1] = 'invalid';
-            sendBadge(format, badgeData);
+            badgeData.text[1] = 'invalid'
+            sendBadge(format, badgeData)
           }
-        });
+        })
       }
 
       if (version === 'latest') {
-        const url = `/repos/${user}/${repo}/releases/latest`;
+        const url = `/repos/${user}/${repo}/releases/latest`
         githubApiProvider.request(request, url, {}, (err, res, buffer) => {
           if (err != null) {
-            badgeData.text[1] = 'inaccessible';
-            sendBadge(format, badgeData);
-            return;
+            badgeData.text[1] = 'inaccessible'
+            sendBadge(format, badgeData)
+            return
           }
           try {
-            const data = JSON.parse(buffer);
-            setCommitsSinceBadge(user, repo, data.tag_name);
+            const data = JSON.parse(buffer)
+            setCommitsSinceBadge(user, repo, data.tag_name)
           } catch (e) {
-            badgeData.text[1] = 'invalid';
-            sendBadge(format, badgeData);
+            badgeData.text[1] = 'invalid'
+            sendBadge(format, badgeData)
           }
-        });
+        })
       } else {
-        setCommitsSinceBadge(user, repo, version);
+        setCommitsSinceBadge(user, repo, version)
       }
-    }));
+    })
+  )
 }
 
 //Github Release & Pre-Release Date Integration release-date-pre (?:\/(all))?
 function mapGithubReleaseDate({ camp, cache }, githubApiProvider) {
-  camp.route(/^\/github\/(release-date|release-date-pre)\/([^/]+)\/([^/]+)\.(svg|png|gif|jpg|json)$/,
-    cache(function (data, match, sendBadge, request) {
-      const releaseType = match[1]; // eg, release-date-pre / release-date
-      const user = match[2];  // eg, microsoft
-      const repo = match[3];  // eg, vscode
-      const format = match[4];
-      let apiUrl = `/repos/${user}/${repo}/releases`;
-      if(releaseType === 'release-date') {
-        apiUrl += '/latest';
+  camp.route(
+    /^\/github\/(release-date|release-date-pre)\/([^/]+)\/([^/]+)\.(svg|png|gif|jpg|json)$/,
+    cache(function(data, match, sendBadge, request) {
+      const releaseType = match[1] // eg, release-date-pre / release-date
+      const user = match[2] // eg, microsoft
+      const repo = match[3] // eg, vscode
+      const format = match[4]
+      let apiUrl = `/repos/${user}/${repo}/releases`
+      if (releaseType === 'release-date') {
+        apiUrl += '/latest'
       }
-      const badgeData = getBadgeData('release date', data);
+      const badgeData = getBadgeData('release date', data)
       if (badgeData.template === 'social') {
-        badgeData.logo = getLogo('github', data);
+        badgeData.logo = getLogo('github', data)
       }
       githubApiProvider.request(request, apiUrl, {}, (err, res, buffer) => {
         if (err != null) {
-          badgeData.text[1] = 'inaccessible';
-          sendBadge(format, badgeData);
-          return;
+          badgeData.text[1] = 'inaccessible'
+          sendBadge(format, badgeData)
+          return
         }
 
         //github return 404 if repo not found or no release
-        if(res.statusCode === 404) {
-          badgeData.text[1] = 'no releases or repo not found';
-          sendBadge(format, badgeData);
-          return;
+        if (res.statusCode === 404) {
+          badgeData.text[1] = 'no releases or repo not found'
+          sendBadge(format, badgeData)
+          return
         }
 
         try {
-          let data = JSON.parse(buffer);
-          if(releaseType === 'release-date-pre') {
-            data = data[0];
+          let data = JSON.parse(buffer)
+          if (releaseType === 'release-date-pre') {
+            data = data[0]
           }
-          const releaseDate = moment(data.created_at);
-          badgeData.text[1] = formatDate(releaseDate);
-          badgeData.colorscheme = age(releaseDate);
-          sendBadge(format, badgeData);
+          const releaseDate = moment(data.created_at)
+          badgeData.text[1] = formatDate(releaseDate)
+          badgeData.colorscheme = age(releaseDate)
+          sendBadge(format, badgeData)
         } catch (e) {
-          badgeData.text[1] = 'invalid';
-          sendBadge(format, badgeData);
+          badgeData.text[1] = 'invalid'
+          sendBadge(format, badgeData)
         }
-      });
-    }));
+      })
+    })
+  )
 }
 
-
 module.exports = {
   mapGithubCommitsSince,
-  mapGithubReleaseDate
-};
+  mapGithubReleaseDate,
+}
diff --git a/lib/in-process-server-test-helpers.js b/lib/in-process-server-test-helpers.js
index 1f5c166f6a6a0fb7dd92cb131e2915b4ed6e2caf..4679a8c9c821a1ef9ea8784d45c21e0796105882 100644
--- a/lib/in-process-server-test-helpers.js
+++ b/lib/in-process-server-test-helpers.js
@@ -10,11 +10,11 @@
  * after('Shut down the server', function () { serverHelpers.stop(server); });
  */
 
-'use strict';
+'use strict'
 
-const config = require('./test-config');
+const config = require('./test-config')
 
-let startCalled = false;
+let startCalled = false
 
 /**
  * Start the server.
@@ -22,21 +22,23 @@ let startCalled = false;
  * @param {Number} port number (optional)
  * @return {Object} The scoutcamp instance
  */
-function start () {
+function start() {
   if (startCalled) {
-    throw Error('Because of the way Shields works, you can only use this ' +
-      'once per node process. Once you call stop(), the game is over.');
+    throw Error(
+      'Because of the way Shields works, you can only use this ' +
+        'once per node process. Once you call stop(), the game is over.'
+    )
   }
-  startCalled = true;
+  startCalled = true
 
-  const originalArgv = process.argv;
+  const originalArgv = process.argv
   // Modifying argv during import is a bit dirty, but it works, and avoids
   // making bigger changes to server.js.
-  process.argv = ['', '', config.port, 'localhost'];
-  const server = require('../server');
+  process.argv = ['', '', config.port, 'localhost']
+  const server = require('../server')
 
-  process.argv = originalArgv;
-  return server;
+  process.argv = originalArgv
+  return server
 }
 
 /**
@@ -44,8 +46,8 @@ function start () {
  *
  * @param {Object} server instance
  */
-function reset (server) {
-  server.reset();
+function reset(server) {
+  server.reset()
 }
 
 /**
@@ -53,14 +55,14 @@ function reset (server) {
  *
  * @param {Object} server instance
  */
-function stop (server) {
+function stop(server) {
   if (server) {
-    server.stop();
+    server.stop()
   }
 }
 
 module.exports = {
   start,
   reset,
-  stop
-};
+  stop,
+}
diff --git a/lib/licenses.js b/lib/licenses.js
index f131128062839f59ecb30dae84c8ae4ec460b7e5..544345b63c18922ebd381c92a78782169bdc8edd 100644
--- a/lib/licenses.js
+++ b/lib/licenses.js
@@ -1,33 +1,62 @@
-'use strict';
+'use strict'
 const licenseTypes = {
   // permissive licenses - not public domain and not copyleft
-  'permissive': {
-    spdxLicenseIds: ['AFL-3.0', 'Apache-2.0', 'Artistic-2.0', 'BSD-2-Clause', 'BSD-3-Clause', 'BSD-3-Clause-Clear',
-      'BSL-1.0', 'CC-BY-4.0', 'ECL-2.0', 'ISC', 'MIT', 'MS-PL', 'NCSA', 'PostgreSQL', 'Zlib'],
-    color: 'green'
+  permissive: {
+    spdxLicenseIds: [
+      'AFL-3.0',
+      'Apache-2.0',
+      'Artistic-2.0',
+      'BSD-2-Clause',
+      'BSD-3-Clause',
+      'BSD-3-Clause-Clear',
+      'BSL-1.0',
+      'CC-BY-4.0',
+      'ECL-2.0',
+      'ISC',
+      'MIT',
+      'MS-PL',
+      'NCSA',
+      'PostgreSQL',
+      'Zlib',
+    ],
+    color: 'green',
   },
   // copyleft licenses require 'Disclose source' (https://choosealicense.com/appendix/#disclose-source)
   // or 'Same license' (https://choosealicense.com/appendix/#same-license)
-  'copyleft': {
-    spdxLicenseIds: ['AGPL-3.0', 'CC-BY-SA-4.0', 'EPL-1.0', 'EUPL-1.1', 'GPL-2.0', 'GPL-3.0', 'LGPL-2.1', 'LGPL-3.0',
-      'LPPL-1.3c', 'MPL-2.0', 'MS-RL', 'OFL-1.1', 'OSL-3.0'],
-    color: 'orange'
+  copyleft: {
+    spdxLicenseIds: [
+      'AGPL-3.0',
+      'CC-BY-SA-4.0',
+      'EPL-1.0',
+      'EUPL-1.1',
+      'GPL-2.0',
+      'GPL-3.0',
+      'LGPL-2.1',
+      'LGPL-3.0',
+      'LPPL-1.3c',
+      'MPL-2.0',
+      'MS-RL',
+      'OFL-1.1',
+      'OSL-3.0',
+    ],
+    color: 'orange',
   },
   // public domain licenses do not require 'License and copyright notice' (https://choosealicense.com/appendix/#include-copyright)
   'public-domain': {
     spdxLicenseIds: ['CC0-1.0', 'Unlicense', 'WTFPL'],
-    color: '7cd958'
-  }
-};
+    color: '7cd958',
+  },
+}
 
-const licenseToColorMap = {};
+const licenseToColorMap = {}
 Object.keys(licenseTypes).forEach(licenseType => {
-  const { spdxLicenseIds, color } = licenseTypes[licenseType];
+  const { spdxLicenseIds, color } = licenseTypes[licenseType]
   spdxLicenseIds.forEach(license => {
-    licenseToColorMap[license] = color;
-  });
-});
-const defaultLicenseColor = 'lightgrey';
-const licenseToColor = (spdxId) => licenseToColorMap[spdxId] || defaultLicenseColor;
+    licenseToColorMap[license] = color
+  })
+})
+const defaultLicenseColor = 'lightgrey'
+const licenseToColor = spdxId =>
+  licenseToColorMap[spdxId] || defaultLicenseColor
 
-module.exports = { licenseToColor };
+module.exports = { licenseToColor }
diff --git a/lib/licenses.spec.js b/lib/licenses.spec.js
index 1e3fc3834484520b2ce927da44c66f9a43842321..8ac6910912257f650af1730cef4cd92a95c91245 100644
--- a/lib/licenses.spec.js
+++ b/lib/licenses.spec.js
@@ -1,14 +1,14 @@
-'use strict';
+'use strict'
 
-const {test, given} = require('sazerac');
-const {licenseToColor} = require('./licenses');
+const { test, given } = require('sazerac')
+const { licenseToColor } = require('./licenses')
 
 describe('license helpers', () => {
   test(licenseToColor, () => {
-    given('MIT').expect('green');
-    given('MPL-2.0').expect('orange');
-    given('Unlicense').expect('7cd958');
-    given('unknown-license').expect('lightgrey');
-    given(null).expect('lightgrey');
-  });
-});
+    given('MIT').expect('green')
+    given('MPL-2.0').expect('orange')
+    given('Unlicense').expect('7cd958')
+    given('unknown-license').expect('lightgrey')
+    given(null).expect('lightgrey')
+  })
+})
diff --git a/lib/load-logos.js b/lib/load-logos.js
index e7503f5c0112e9701212a03554fbcc553f53c3be..e9c2ec049ff392c0006fbd5ea45621a3f21f7dfc 100644
--- a/lib/load-logos.js
+++ b/lib/load-logos.js
@@ -1,28 +1,30 @@
-'use strict';
+'use strict'
 
-const fs = require('fs');
-const path = require('path');
-const { svg2base64 } = require('./logo-helper');
+const fs = require('fs')
+const path = require('path')
+const { svg2base64 } = require('./logo-helper')
 
-function loadLogos () {
+function loadLogos() {
   // Cache svg logos from disk in base64 string
-  const logos = {};
-  const logoDir = path.join(__dirname, '..', 'logo');
-  const logoFiles = fs.readdirSync(logoDir);
+  const logos = {}
+  const logoDir = path.join(__dirname, '..', 'logo')
+  const logoFiles = fs.readdirSync(logoDir)
   logoFiles.forEach(function(filename) {
-    if (filename[0] === '.') { return; }
+    if (filename[0] === '.') {
+      return
+    }
     // filename is eg, github.svg
-    const svg = fs.readFileSync(logoDir + '/' + filename).toString();
-    const base64 = svg2base64(svg);
+    const svg = fs.readFileSync(logoDir + '/' + filename).toString()
+    const base64 = svg2base64(svg)
 
     // eg, github
-    const name = filename.slice(0, -('.svg'.length)).toLowerCase();
+    const name = filename.slice(0, -'.svg'.length).toLowerCase()
     logos[name] = {
       svg,
-      base64
-    };
-  });
-  return logos;
+      base64,
+    }
+  })
+  return logos
 }
 
-module.exports = loadLogos;
+module.exports = loadLogos
diff --git a/lib/load-simple-icons.js b/lib/load-simple-icons.js
index 278f381c19e7dc7f49b1ef7d0dbeac8a29712593..f7f8d8f17df4ca0a118f154c617381fb3d920047 100644
--- a/lib/load-simple-icons.js
+++ b/lib/load-simple-icons.js
@@ -1,18 +1,20 @@
-'use strict';
+'use strict'
 
-const simpleIcons = require('simple-icons');
-const { svg2base64 } = require('./logo-helper');
+const simpleIcons = require('simple-icons')
+const { svg2base64 } = require('./logo-helper')
 
-function loadSimpleIcons(){
-  Object.keys(simpleIcons).forEach(function (key) {
-    const k = key.toLowerCase().replace(/ /g, '-');
+function loadSimpleIcons() {
+  Object.keys(simpleIcons).forEach(function(key) {
+    const k = key.toLowerCase().replace(/ /g, '-')
     if (k !== key) {
-      simpleIcons[k] = simpleIcons[key];
-      delete simpleIcons[key];
+      simpleIcons[k] = simpleIcons[key]
+      delete simpleIcons[key]
     }
-    simpleIcons[k].base64 = svg2base64(simpleIcons[k].svg.replace('<svg', `<svg fill="#${simpleIcons[k].hex}"`));
-  });
-  return (simpleIcons);
+    simpleIcons[k].base64 = svg2base64(
+      simpleIcons[k].svg.replace('<svg', `<svg fill="#${simpleIcons[k].hex}"`)
+    )
+  })
+  return simpleIcons
 }
 
-module.exports = loadSimpleIcons;
+module.exports = loadSimpleIcons
diff --git a/lib/log.js b/lib/log.js
index e12aca9000cdcc8bf211dc8305ebb38d158cf894..2f0cd06981fa144b36562fcda276cc31223d87e8 100644
--- a/lib/log.js
+++ b/lib/log.js
@@ -1,52 +1,61 @@
-'use strict';
-const Raven = require('raven');
-const throttle = require('lodash.throttle');
+'use strict'
+const Raven = require('raven')
+const throttle = require('lodash.throttle')
 
-const listeners = [];
+const listeners = []
 
 // Zero-pad a number in a string.
 // eg. 4 becomes 04 but 17 stays 17.
 function pad(string) {
-  string = String(string);
-  return (string.length < 2) ? ('0' + string) : string;
+  string = String(string)
+  return string.length < 2 ? '0' + string : string
 }
 
 // Compact date representation.
 // eg. 0611093840 for June 11, 9:38:40 UTC.
 function date() {
-  const date = new Date();
-  return pad(date.getUTCMonth() + 1) +
+  const date = new Date()
+  return (
+    pad(date.getUTCMonth() + 1) +
     pad(date.getUTCDate()) +
     pad(date.getUTCHours()) +
     pad(date.getUTCMinutes()) +
-    pad(date.getUTCSeconds());
+    pad(date.getUTCSeconds())
+  )
 }
 
 module.exports = function log(...msg) {
-  const d = date();
+  const d = date()
   listeners.forEach(f => f(d, ...msg))
-  console.log(d, ...msg);
-};
+  console.log(d, ...msg)
+}
 
-const throttledConsoleError = throttle(console.error, 10000, { trailing: false });
+const throttledConsoleError = throttle(console.error, 10000, {
+  trailing: false,
+})
 
 module.exports.error = function error(...msg) {
-  const d = date();
-  listeners.forEach(f => f(d, ...msg));
-  Raven.captureException(msg, function (sendErr) {
+  const d = date()
+  listeners.forEach(f => f(d, ...msg))
+  Raven.captureException(msg, function(sendErr) {
     if (sendErr) {
-      throttledConsoleError('Failed to send captured exception to Sentry', sendErr.message);
+      throttledConsoleError(
+        'Failed to send captured exception to Sentry',
+        sendErr.message
+      )
     }
-  });
-  console.error(d, ...msg);
-};
+  })
+  console.error(d, ...msg)
+}
 
 module.exports.addListener = function addListener(func) {
-  listeners.push(func);
-};
+  listeners.push(func)
+}
 
 module.exports.removeListener = function removeListener(func) {
-  const index = listeners.indexOf(func);
-  if (index < 0) { return; }
-  listeners.splice(index, 1);
-};
+  const index = listeners.indexOf(func)
+  if (index < 0) {
+    return
+  }
+  listeners.splice(index, 1)
+}
diff --git a/lib/log.spec.js b/lib/log.spec.js
index 7bf809f374b8caf04b4ddf536d1681dcfa56a89c..a5804be0b0353fc6ea8aa295bbf43786141d0787 100644
--- a/lib/log.spec.js
+++ b/lib/log.spec.js
@@ -1,48 +1,65 @@
-'use strict';
-const chai = require('chai');
-const expect = chai.expect;
-const sinon = require('sinon');
-const sinonChai = require('sinon-chai');;
-const Raven = require('raven');
+'use strict'
+const chai = require('chai')
+const expect = chai.expect
+const sinon = require('sinon')
+const sinonChai = require('sinon-chai')
+const Raven = require('raven')
 
-chai.use(sinonChai);
+chai.use(sinonChai)
 
-function requireUncached(module){
-    delete require.cache[require.resolve(module)]
-    return require(module)
+function requireUncached(module) {
+  delete require.cache[require.resolve(module)]
+  return require(module)
 }
 
-describe('log', ()  => {
-    describe('error', () => {
-        before(() => {
-            this.clock = sinon.useFakeTimers();
-            sinon.stub(Raven, 'captureException').callsFake(function fakeFn(e, callback) {
-                callback(new Error(`Cannot send message "${e}" to Sentry.`));
-            });
-            // we have to create a spy before requiring 'error' function
-            sinon.spy(console, 'error');
-            this.error = requireUncached('./log').error;
-        });
-        
-        after(() =>  {
-            this.clock.restore();
-            console.error.restore();
-            Raven.captureException.restore();
-        });
-        
-        it('should throttle errors from Raven client', () => {
-            this.error('test error 1');
-            this.error('test error 2');
-            this.error('test error 3');
-            this.clock.tick(11000);
-            this.error('test error 4');
-            this.error('test error 5');
+describe('log', () => {
+  describe('error', () => {
+    before(() => {
+      this.clock = sinon.useFakeTimers()
+      sinon
+        .stub(Raven, 'captureException')
+        .callsFake(function fakeFn(e, callback) {
+          callback(new Error(`Cannot send message "${e}" to Sentry.`))
+        })
+      // we have to create a spy before requiring 'error' function
+      sinon.spy(console, 'error')
+      this.error = requireUncached('./log').error
+    })
 
-            expect(console.error).to.be.calledWithExactly('Failed to send captured exception to Sentry', 'Cannot send message "test error 1" to Sentry.');
-            expect(console.error).to.not.be.calledWithExactly('Failed to send captured exception to Sentry', 'Cannot send message "test error 2" to Sentry.');
-            expect(console.error).to.not.be.calledWithExactly('Failed to send captured exception to Sentry', 'Cannot send message "test error 3" to Sentry.');
-            expect(console.error).to.be.calledWithExactly('Failed to send captured exception to Sentry', 'Cannot send message "test error 4" to Sentry.');
-            expect(console.error).to.not.be.calledWithExactly('Failed to send captured exception to Sentry', 'Cannot send message "test error 5" to Sentry.');
-        });
-    });
-});
+    after(() => {
+      this.clock.restore()
+      console.error.restore()
+      Raven.captureException.restore()
+    })
+
+    it('should throttle errors from Raven client', () => {
+      this.error('test error 1')
+      this.error('test error 2')
+      this.error('test error 3')
+      this.clock.tick(11000)
+      this.error('test error 4')
+      this.error('test error 5')
+
+      expect(console.error).to.be.calledWithExactly(
+        'Failed to send captured exception to Sentry',
+        'Cannot send message "test error 1" to Sentry.'
+      )
+      expect(console.error).to.not.be.calledWithExactly(
+        'Failed to send captured exception to Sentry',
+        'Cannot send message "test error 2" to Sentry.'
+      )
+      expect(console.error).to.not.be.calledWithExactly(
+        'Failed to send captured exception to Sentry',
+        'Cannot send message "test error 3" to Sentry.'
+      )
+      expect(console.error).to.be.calledWithExactly(
+        'Failed to send captured exception to Sentry',
+        'Cannot send message "test error 4" to Sentry.'
+      )
+      expect(console.error).to.not.be.calledWithExactly(
+        'Failed to send captured exception to Sentry',
+        'Cannot send message "test error 5" to Sentry.'
+      )
+    })
+  })
+})
diff --git a/lib/logo-helper.js b/lib/logo-helper.js
index 93d88535c16cbe0a1f6526b73baac9666d04ef14..bcec10cc612adde769249cc7a70b23882d1d8957 100644
--- a/lib/logo-helper.js
+++ b/lib/logo-helper.js
@@ -1,15 +1,17 @@
-'use strict';
+'use strict'
 
 function isDataUri(s) {
-  return s !== undefined && /^(data:)([^;]+);([^,]+),(.+)$/.test(s);
+  return s !== undefined && /^(data:)([^;]+);([^,]+),(.+)$/.test(s)
 }
 
-function svg2base64(svg){
-  if (typeof svg !== 'string'){
-    return undefined;
+function svg2base64(svg) {
+  if (typeof svg !== 'string') {
+    return undefined
   }
   // Check if logo is already base64
-  return isDataUri(svg) ? svg : 'data:image/svg+xml;base64,' + Buffer.from(svg).toString('base64');
+  return isDataUri(svg)
+    ? svg
+    : 'data:image/svg+xml;base64,' + Buffer.from(svg).toString('base64')
 }
 
 module.exports = {
diff --git a/lib/logo-helper.spec.js b/lib/logo-helper.spec.js
index 0efc4b17edc0f412688c54734167521df8eb58e3..2acdad7b36082768ec948419dba17dacb1531bdc 100644
--- a/lib/logo-helper.spec.js
+++ b/lib/logo-helper.spec.js
@@ -1,27 +1,21 @@
-'use strict';
+'use strict'
 
-const {
-  test,
-  given,
-  forCases,
-} = require('sazerac');
-const {
-  svg2base64,
-  isDataUri,
-} = require('./logo-helper');
+const { test, given, forCases } = require('sazerac')
+const { svg2base64, isDataUri } = require('./logo-helper')
 
 describe('Logo helpers', function() {
   test(svg2base64, () => {
-    given('data:image/svg+xml;base64,PHN2ZyB4bWxu').expect('data:image/svg+xml;base64,PHN2ZyB4bWxu');
-    given('<svg xmlns="http://www.w3.org/2000/svg"/>').expect('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLz4=');
-    given(undefined).expect(undefined);
-  });
+    given('data:image/svg+xml;base64,PHN2ZyB4bWxu').expect(
+      'data:image/svg+xml;base64,PHN2ZyB4bWxu'
+    )
+    given('<svg xmlns="http://www.w3.org/2000/svg"/>').expect(
+      'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLz4='
+    )
+    given(undefined).expect(undefined)
+  })
 
   test(isDataUri, () => {
-    given('data:image/svg+xml;base64,PHN2ZyB4bWxu').expect(true);
-    forCases([
-      given('data:foobar'),
-      given('foobar'),
-    ]).expect(false);
-  });
-});
+    given('data:image/svg+xml;base64,PHN2ZyB4bWxu').expect(true)
+    forCases([given('data:foobar'), given('foobar')]).expect(false)
+  })
+})
diff --git a/lib/lru-cache.js b/lib/lru-cache.js
index 6a5959521ee598f2add0eeaf0efe3f6b1f2ec5dd..2ed2942152a1ef1639322137f1bba443ef345719 100644
--- a/lib/lru-cache.js
+++ b/lib/lru-cache.js
@@ -1,132 +1,138 @@
-'use strict';
+'use strict'
 
 // In-memory KV, remove the oldest data when the capacity is reached.
 
 const typeEnum = {
   unit: 0,
   heap: 1,
-};
+}
 
 function CacheSlot(key, value) {
-  this.key = key;
-  this.value = value;
-  this.older = null;  // Newest slot that is older than this slot.
-  this.newer = null;  // Oldest slot that is newer than this slot.
+  this.key = key
+  this.value = value
+  this.older = null // Newest slot that is older than this slot.
+  this.newer = null // Oldest slot that is newer than this slot.
 }
 
 function Cache(capacity, type) {
-  if (!(this instanceof Cache)) { return new Cache(capacity, type); }
-  type = type || 'unit';
-  this.capacity = capacity;
-  this.type = typeEnum[type];
-  this.cache = new Map();  // Maps cache keys to CacheSlots.
-  this.newest = null;  // Newest slot in the cache.
-  this.oldest = null;
+  if (!(this instanceof Cache)) {
+    return new Cache(capacity, type)
+  }
+  type = type || 'unit'
+  this.capacity = capacity
+  this.type = typeEnum[type]
+  this.cache = new Map() // Maps cache keys to CacheSlots.
+  this.newest = null // Newest slot in the cache.
+  this.oldest = null
 }
 
 Cache.prototype = {
   set: function addToCache(cacheKey, cached) {
-    let slot = this.cache.get(cacheKey);
+    let slot = this.cache.get(cacheKey)
     if (slot === undefined) {
-      slot = new CacheSlot(cacheKey, cached);
-      this.cache.set(cacheKey, slot);
+      slot = new CacheSlot(cacheKey, cached)
+      this.cache.set(cacheKey, slot)
     }
-    this.makeNewest(slot);
-    const numItemsToRemove = this.limitReached();
+    this.makeNewest(slot)
+    const numItemsToRemove = this.limitReached()
     if (numItemsToRemove > 0) {
       for (let i = 0; i < numItemsToRemove; i++) {
-        this.removeOldest();
+        this.removeOldest()
       }
     }
   },
 
   get: function getFromCache(cacheKey) {
-    const slot = this.cache.get(cacheKey);
+    const slot = this.cache.get(cacheKey)
     if (slot !== undefined) {
-      this.makeNewest(slot);
-      return slot.value;
+      this.makeNewest(slot)
+      return slot.value
     }
   },
 
   has: function hasInCache(cacheKey) {
-    return this.cache.has(cacheKey);
+    return this.cache.has(cacheKey)
   },
 
   makeNewest: function makeNewestSlot(slot) {
-    const previousNewest = this.newest;
-    if (previousNewest === slot) { return; }
-    const older = slot.older;
-    const newer = slot.newer;
+    const previousNewest = this.newest
+    if (previousNewest === slot) {
+      return
+    }
+    const older = slot.older
+    const newer = slot.newer
 
     if (older !== null) {
-      older.newer = newer;
+      older.newer = newer
     } else if (newer !== null) {
-      this.oldest = newer;
+      this.oldest = newer
     }
     if (newer !== null) {
-      newer.older = older;
+      newer.older = older
     }
-    this.newest = slot;
+    this.newest = slot
 
     if (previousNewest !== null) {
-      slot.older = previousNewest;
-      slot.newer = null;
-      previousNewest.newer = slot;
+      slot.older = previousNewest
+      slot.newer = null
+      previousNewest.newer = slot
     } else {
       // If previousNewest is null, the cache used to be empty.
-      this.oldest = slot;
+      this.oldest = slot
     }
   },
 
   removeOldest: function removeOldest() {
-    const cacheKey = this.oldest.key;
+    const cacheKey = this.oldest.key
     if (this.oldest !== null) {
-      this.oldest = this.oldest.newer;
+      this.oldest = this.oldest.newer
       if (this.oldest !== null) {
-        this.oldest.older = null;
+        this.oldest.older = null
       }
     }
-    this.cache.delete(cacheKey);
+    this.cache.delete(cacheKey)
   },
 
   // Returns the number of elements to remove if we're past the limit.
   limitReached: function heuristic() {
     if (this.type === typeEnum.unit) {
       // Remove the excess.
-      return Math.max(0, (this.cache.size - this.capacity));
+      return Math.max(0, this.cache.size - this.capacity)
     } else if (this.type === typeEnum.heap) {
       if (getHeapSize() >= this.capacity) {
-        console.log('LRU HEURISTIC heap:', getHeapSize());
+        console.log('LRU HEURISTIC heap:', getHeapSize())
         // Remove half of them.
-        return (this.cache.size >> 1);
-      } else { return 0; }
+        return this.cache.size >> 1
+      } else {
+        return 0
+      }
     } else {
-      console.error("Unknown heuristic '" + this.type + "' for LRU cache.");
-      return 1;
+      console.error("Unknown heuristic '" + this.type + "' for LRU cache.")
+      return 1
     }
   },
 
-  clear: function () {
-    this.cache.clear();
-    this.newest = null;
-    this.oldest = null;
-  }
-};
+  clear: function() {
+    this.cache.clear()
+    this.newest = null
+    this.oldest = null
+  },
+}
 
 // In bytes.
-let heapSize;
-let heapSizeTimeout;
+let heapSize
+let heapSizeTimeout
 function getHeapSize() {
   if (heapSizeTimeout == null) {
     // Compute the heap size every 60 seconds.
-    heapSizeTimeout = setInterval(computeHeapSize, 60 * 1000);
-    return computeHeapSize();
+    heapSizeTimeout = setInterval(computeHeapSize, 60 * 1000)
+    return computeHeapSize()
   } else {
-    return heapSize;
+    return heapSize
   }
 }
 function computeHeapSize() {
-  return (heapSize = process.memoryUsage().heapTotal);
+  return (heapSize = process.memoryUsage().heapTotal)
 }
 
-module.exports = Cache;
+module.exports = Cache
diff --git a/lib/lru-cache.spec.js b/lib/lru-cache.spec.js
index 67a33cb5bc649c1a0dabce1ca3ee0f55d29c405d..754753334850c80489843f89b94508422e3d8297 100644
--- a/lib/lru-cache.spec.js
+++ b/lib/lru-cache.spec.js
@@ -1,139 +1,139 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const LRU = require('./lru-cache');
+const { expect } = require('chai')
+const LRU = require('./lru-cache')
 
 function expectCacheSlots(cache, keys) {
-  expect(cache.cache.size).to.equal(keys.length);
+  expect(cache.cache.size).to.equal(keys.length)
 
-  const slots = keys.map(k => cache.cache.get(k));
+  const slots = keys.map(k => cache.cache.get(k))
 
-  const first = slots[0];
-  const last = slots.slice(-1)[0];
+  const first = slots[0]
+  const last = slots.slice(-1)[0]
 
-  expect(cache.oldest).to.equal(first);
-  expect(cache.newest).to.equal(last);
+  expect(cache.oldest).to.equal(first)
+  expect(cache.newest).to.equal(last)
 
-  expect(first.older).to.be.null;
-  expect(last.newer).to.be.null;
+  expect(first.older).to.be.null
+  expect(last.newer).to.be.null
 
   for (let i = 0; i + 1 < slots.length; ++i) {
-    const current = slots[i];
-    const next = slots[i+1];
-    expect(current.newer).to.equal(next);
-    expect(next.older).to.equal(current);
+    const current = slots[i]
+    const next = slots[i + 1]
+    expect(current.newer).to.equal(next)
+    expect(next.older).to.equal(current)
   }
 }
 
-describe('The LRU cache', function () {
-  it('should support being called without new', function () {
-    const cache = LRU(1);
-    expect(cache).to.be.an.instanceof(LRU);
-  });
+describe('The LRU cache', function() {
+  it('should support being called without new', function() {
+    const cache = LRU(1)
+    expect(cache).to.be.an.instanceof(LRU)
+  })
 
-  it('should support a zero capacity', function () {
-    const cache = new LRU(0);
-    cache.set('key', 'value');
-    expect(cache.cache.size).to.equal(0);
-  });
+  it('should support a zero capacity', function() {
+    const cache = new LRU(0)
+    cache.set('key', 'value')
+    expect(cache.cache.size).to.equal(0)
+  })
 
-  it('should support a one capacity', function () {
-    const cache = new LRU(1);
-    cache.set('key1', 'value1');
-    expectCacheSlots(cache, ['key1']);
-    cache.set('key2', 'value2');
-    expectCacheSlots(cache, ['key2']);
-    expect(cache.get('key1')).to.be.undefined;
-    expect(cache.get('key2')).to.equal('value2');
-  });
+  it('should support a one capacity', function() {
+    const cache = new LRU(1)
+    cache.set('key1', 'value1')
+    expectCacheSlots(cache, ['key1'])
+    cache.set('key2', 'value2')
+    expectCacheSlots(cache, ['key2'])
+    expect(cache.get('key1')).to.be.undefined
+    expect(cache.get('key2')).to.equal('value2')
+  })
 
-  it('should remove the oldest element when reaching capacity', function () {
-    const cache = new LRU(2);
+  it('should remove the oldest element when reaching capacity', function() {
+    const cache = new LRU(2)
 
-    cache.set('key1', 'value1');
-    cache.set('key2', 'value2');
-    cache.set('key3', 'value3');
-    cache.cache.get('key1');
+    cache.set('key1', 'value1')
+    cache.set('key2', 'value2')
+    cache.set('key3', 'value3')
+    cache.cache.get('key1')
 
-    expectCacheSlots(cache, ['key2', 'key3']);
-    expect(cache.cache.get('key1')).to.be.undefined;
-    expect(cache.get('key1')).to.be.undefined;
-    expect(cache.get('key2')).to.equal('value2');
-    expect(cache.get('key3')).to.equal('value3');
-  });
+    expectCacheSlots(cache, ['key2', 'key3'])
+    expect(cache.cache.get('key1')).to.be.undefined
+    expect(cache.get('key1')).to.be.undefined
+    expect(cache.get('key2')).to.equal('value2')
+    expect(cache.get('key3')).to.equal('value3')
+  })
 
-  it('should make sure that resetting a key in cache makes it newest', function () {
-    const cache = new LRU(2);
+  it('should make sure that resetting a key in cache makes it newest', function() {
+    const cache = new LRU(2)
 
-    cache.set('key', 'value');
-    cache.set('key2', 'value2');
+    cache.set('key', 'value')
+    cache.set('key2', 'value2')
 
-    expectCacheSlots(cache, ['key', 'key2']);
+    expectCacheSlots(cache, ['key', 'key2'])
 
-    cache.set('key', 'value');
+    cache.set('key', 'value')
 
-    expectCacheSlots(cache, ['key2', 'key']);
-  });
+    expectCacheSlots(cache, ['key2', 'key'])
+  })
 
-  describe('getting a key in the cache', function () {
-    context('when the requested key is oldest', function () {
-      it('should leave the keys in the expected order', function () {
-        const cache = new LRU(2);
-        cache.set('key1', 'value1');
-        cache.set('key2', 'value2');
+  describe('getting a key in the cache', function() {
+    context('when the requested key is oldest', function() {
+      it('should leave the keys in the expected order', function() {
+        const cache = new LRU(2)
+        cache.set('key1', 'value1')
+        cache.set('key2', 'value2')
 
-        expectCacheSlots(cache, ['key1', 'key2']);
+        expectCacheSlots(cache, ['key1', 'key2'])
 
-        expect(cache.get('key1')).to.equal('value1');
+        expect(cache.get('key1')).to.equal('value1')
 
-        expectCacheSlots(cache, ['key2', 'key1']);
-      });
-    });
+        expectCacheSlots(cache, ['key2', 'key1'])
+      })
+    })
 
-    context('when the requested key is newest', function () {
-      it('should leave the keys in the expected order', function () {
-        const cache = new LRU(2);
-        cache.set('key1', 'value1');
-        cache.set('key2', 'value2');
+    context('when the requested key is newest', function() {
+      it('should leave the keys in the expected order', function() {
+        const cache = new LRU(2)
+        cache.set('key1', 'value1')
+        cache.set('key2', 'value2')
 
-        expect(cache.get('key2')).to.equal('value2');
+        expect(cache.get('key2')).to.equal('value2')
 
-        expectCacheSlots(cache, ['key1', 'key2']);
-      });
-    });
+        expectCacheSlots(cache, ['key1', 'key2'])
+      })
+    })
 
-    context('when the requested key is in the middle', function () {
-      it('should leave the keys in the expected order', function () {
-        const cache = new LRU(3);
-        cache.set('key1', 'value1');
-        cache.set('key2', 'value2');
-        cache.set('key3', 'value3');
+    context('when the requested key is in the middle', function() {
+      it('should leave the keys in the expected order', function() {
+        const cache = new LRU(3)
+        cache.set('key1', 'value1')
+        cache.set('key2', 'value2')
+        cache.set('key3', 'value3')
 
-        expectCacheSlots(cache, ['key1', 'key2', 'key3']);
+        expectCacheSlots(cache, ['key1', 'key2', 'key3'])
 
-        expect(cache.get('key2')).to.equal('value2');
+        expect(cache.get('key2')).to.equal('value2')
 
-        expectCacheSlots(cache, ['key1', 'key3', 'key2']);
-      });
-    });
-  });
+        expectCacheSlots(cache, ['key1', 'key3', 'key2'])
+      })
+    })
+  })
 
-  it('should clear', function () {
+  it('should clear', function() {
     // Set up.
-    const cache = new LRU(2);
-    cache.set('key1', 'value1');
-    cache.set('key2', 'value2');
+    const cache = new LRU(2)
+    cache.set('key1', 'value1')
+    cache.set('key2', 'value2')
 
     // Confidence check.
-    expect(cache.get('key1')).to.equal('value1');
-    expect(cache.get('key2')).to.equal('value2');
+    expect(cache.get('key1')).to.equal('value1')
+    expect(cache.get('key2')).to.equal('value2')
 
     // Run.
-    cache.clear();
+    cache.clear()
 
     // Test.
-    expect(cache.get('key1')).to.be.undefined;
-    expect(cache.get('key2')).to.be.undefined;
-    expect(cache.cache.size).to.equal(0);
-  });
-});
+    expect(cache.get('key1')).to.be.undefined
+    expect(cache.get('key2')).to.be.undefined
+    expect(cache.cache.size).to.equal(0)
+  })
+})
diff --git a/lib/luarocks-version.js b/lib/luarocks-version.js
index 563a3365bbaea7854e8566454e8396c46de69030..d2b73d84d2d42309136ad06cda448e74dc2671d9 100644
--- a/lib/luarocks-version.js
+++ b/lib/luarocks-version.js
@@ -3,7 +3,7 @@
  * This compares version numbers using the algorithm
  * followed by luarocks command-line utility
  */
-'use strict';
+'use strict'
 
 // Compare two arrays containing splitted and transformed to
 // positive/negative numbers parts of version strings,
@@ -13,30 +13,30 @@
 // zero if v1 = v2,
 // a positive value otherwise.
 function compareVersionLists(v1, v2) {
-  const maxLength = Math.max(v1.length, v2.length);
-  let p1, p2;
+  const maxLength = Math.max(v1.length, v2.length)
+  let p1, p2
   for (let i = 0; i < maxLength; i++) {
-    p1 = v1[i] || 0;
-    p2 = v2[i] || 0;
-    if (p1 > p2) return 1;
-    if (p1 < p2) return -1;
+    p1 = v1[i] || 0
+    p2 = v2[i] || 0
+    if (p1 > p2) return 1
+    if (p1 < p2) return -1
   }
-  return 0;
+  return 0
 }
-exports.compareVersionLists = compareVersionLists;
+exports.compareVersionLists = compareVersionLists
 
 // Parse a dotted version string to an array of numbers
 // 'rc', 'pre', 'beta', 'alpha' are converted to negative numbers
 function parseVersion(versionString) {
-  versionString = versionString.toLowerCase().replace('-', '.');
-  const versionList = [];
+  versionString = versionString.toLowerCase().replace('-', '.')
+  const versionList = []
   versionString.split('.').forEach(function(versionPart) {
-    const parsedPart = /(\d*)([a-z]*)(\d*)/.exec(versionPart);
+    const parsedPart = /(\d*)([a-z]*)(\d*)/.exec(versionPart)
     if (parsedPart[1]) {
-      versionList.push(parseInt(parsedPart[1]));
+      versionList.push(parseInt(parsedPart[1]))
     }
     if (parsedPart[2]) {
-      let weight;
+      let weight
       // calculate weight as a negative number
       // 'rc' > 'pre' > 'beta' > 'alpha' > any other value
       switch (parsedPart[2]) {
@@ -44,16 +44,16 @@ function parseVersion(versionString) {
         case 'beta':
         case 'pre':
         case 'rc':
-          weight = (parsedPart[2].charCodeAt(0) - 128) * 100;
-          break;
+          weight = (parsedPart[2].charCodeAt(0) - 128) * 100
+          break
         default:
-          weight = -10000;
+          weight = -10000
       }
       // add positive number, i.e. 'beta5' > 'beta2'
-      weight += parseInt(parsedPart[3]) || 0;
-      versionList.push(weight);
+      weight += parseInt(parsedPart[3]) || 0
+      versionList.push(weight)
     }
-  });
-  return versionList;
+  })
+  return versionList
 }
-exports.parseVersion = parseVersion;
+exports.parseVersion = parseVersion
diff --git a/lib/luarocks-version.spec.js b/lib/luarocks-version.spec.js
index f9dcf2b1162d1f39a5b65b1a69c30fb11e2297e3..1cce5bb2194ad926b161b5fc5905c44c2410bc74 100644
--- a/lib/luarocks-version.spec.js
+++ b/lib/luarocks-version.spec.js
@@ -1,7 +1,7 @@
-'use strict';
+'use strict'
 
-const { test, given, forCases } = require('sazerac');
-const {parseVersion, compareVersionLists} = require('./luarocks-version');
+const { test, given, forCases } = require('sazerac')
+const { parseVersion, compareVersionLists } = require('./luarocks-version')
 
 describe('LuaRocks-specific helpers', function() {
   test(compareVersionLists, () => {
@@ -11,9 +11,10 @@ describe('LuaRocks-specific helpers', function() {
       given([1, 2], [1, 2, 0, 0]),
       given([-1, -2], [-1, -2, 0, 0]),
       given([], []),
-    ]).describe('when given [%s] and [%s]')
+    ])
+      .describe('when given [%s] and [%s]')
       .expect(0)
-      .should('should be equal');
+      .should('should be equal')
 
     forCases([
       given([1, 2], [2, 1]),
@@ -22,9 +23,10 @@ describe('LuaRocks-specific helpers', function() {
       given([3, 2, -1], [3, 2]),
       given([-1], []),
       given([], [1]),
-    ]).describe('when given [%s] and [%s]')
+    ])
+      .describe('when given [%s] and [%s]')
       .expect(-1)
-      .should('should be less');
+      .should('should be less')
 
     forCases([
       given([1, 2, 1, 2], [1, 2, 0, 2]),
@@ -34,17 +36,18 @@ describe('LuaRocks-specific helpers', function() {
       given([1, 2, 0, -1], [1, 2, -1, 1]),
       given([], [-1, 2]),
       given([1, -1], []),
-    ]).describe('when given [%s] and [%s]')
+    ])
+      .describe('when given [%s] and [%s]')
       .expect(1)
-      .should('should be greater');
-  });
+      .should('should be greater')
+  })
 
   test(parseVersion, () => {
-    given('1.2.3-1').expect([1, 2, 3, 1]);
-    given('10.02-3').expect([10, 2, 3]);
-    given('3.0rc1-2').expect([3, 0, -1399, 2]);
-    given('2.0-alpha').expect([2, 0, -3100]);
-    given('2.0-beta').expect([2, 0, -3000]);
-    given('2.0-beta5').expect([2, 0, -2995]);
-  });
-});
+    given('1.2.3-1').expect([1, 2, 3, 1])
+    given('10.02-3').expect([10, 2, 3])
+    given('3.0rc1-2').expect([3, 0, -1399, 2])
+    given('2.0-alpha').expect([2, 0, -3100])
+    given('2.0-beta').expect([2, 0, -3000])
+    given('2.0-beta5').expect([2, 0, -2995])
+  })
+})
diff --git a/lib/make-badge-test-helpers.js b/lib/make-badge-test-helpers.js
index 83fcc1835c521f981e4684e0dcc669061a1c7523..a2a87b5c31505d5378a804717bdb0c19791a7a25 100644
--- a/lib/make-badge-test-helpers.js
+++ b/lib/make-badge-test-helpers.js
@@ -1,17 +1,24 @@
-'use strict';
+'use strict'
 
-const path = require('path');
-const { PDFKitTextMeasurer } = require('./text-measurer');
-const { makeMakeBadgeFn } = require('./make-badge');
+const path = require('path')
+const { PDFKitTextMeasurer } = require('./text-measurer')
+const { makeMakeBadgeFn } = require('./make-badge')
 
 module.exports = {
   font: {
-    path: path.join(__dirname, '..', 'node_modules', 'dejavu-fonts-ttf', 'ttf', 'DejaVuSans.ttf'),
+    path: path.join(
+      __dirname,
+      '..',
+      'node_modules',
+      'dejavu-fonts-ttf',
+      'ttf',
+      'DejaVuSans.ttf'
+    ),
   },
   measurer() {
-    return new PDFKitTextMeasurer(this.font.path);
+    return new PDFKitTextMeasurer(this.font.path)
   },
   makeBadge() {
-    return makeMakeBadgeFn(this.measurer());
+    return makeMakeBadgeFn(this.measurer())
   },
-};
+}
diff --git a/lib/make-badge.js b/lib/make-badge.js
index dfe43523abe4612c4f12bd4680b795d5348cea2c..03ca3498f784b0cc032247c96cc603a2f33200b4 100644
--- a/lib/make-badge.js
+++ b/lib/make-badge.js
@@ -1,176 +1,189 @@
-'use strict';
+'use strict'
 
-const fs = require('fs');
-const path = require('path');
-const SVGO = require('svgo');
-const dot = require('dot');
-const LruCache = require('./lru-cache');
-const isCSSColor = require('is-css-color');
+const fs = require('fs')
+const path = require('path')
+const SVGO = require('svgo')
+const dot = require('dot')
+const LruCache = require('./lru-cache')
+const isCSSColor = require('is-css-color')
 
 // Holds widths of badge keys (left hand side of badge).
-const badgeKeyWidthCache = new LruCache(1000);
+const badgeKeyWidthCache = new LruCache(1000)
 
 // cache templates.
-const templates = {};
-const templateFiles = fs.readdirSync(path.join(__dirname, '..', 'templates'));
-dot.templateSettings.strip = false;  // Do not strip whitespace.
+const templates = {}
+const templateFiles = fs.readdirSync(path.join(__dirname, '..', 'templates'))
+dot.templateSettings.strip = false // Do not strip whitespace.
 templateFiles.forEach(async function(filename) {
-  if (filename[0] === '.') { return; }
-  const templateData = fs.readFileSync(
-    path.join(__dirname, '..', 'templates', filename)).toString();
-  const extension = path.extname(filename).slice(1);
-  const style = filename.slice(0, -(('-template.' + extension).length));
+  if (filename[0] === '.') {
+    return
+  }
+  const templateData = fs
+    .readFileSync(path.join(__dirname, '..', 'templates', filename))
+    .toString()
+  const extension = path.extname(filename).slice(1)
+  const style = filename.slice(0, -('-template.' + extension).length)
   // Compile the template. Necessary to always have a working template.
-  templates[style + '-' + extension] = dot.template(templateData);
+  templates[style + '-' + extension] = dot.template(templateData)
   if (extension === 'svg') {
     // Substitute dot code.
-    const mapping = new Map();
-    let mappingIndex = 1;
+    const mapping = new Map()
+    let mappingIndex = 1
     const untemplatedSvg = templateData.replace(/{{.*?}}/g, function(match) {
       // Weird substitution that currently works for all templates.
-      const mapKey = '99999990' + mappingIndex + '.1';
-      mappingIndex++;
-      mapping.set(mapKey, match);
-      return mapKey;
-    });
+      const mapKey = '99999990' + mappingIndex + '.1'
+      mappingIndex++
+      mapping.set(mapKey, match)
+      return mapKey
+    })
 
-    const svgo = new SVGO();
-    const { data, error } = await svgo.optimize(untemplatedSvg);
+    const svgo = new SVGO()
+    const { data, error } = await svgo.optimize(untemplatedSvg)
 
     if (error !== undefined) {
-      console.error(`Template ${filename}: ${error}\n` +
-        '  Generated untemplated SVG:\n' +
-        `---\n${untemplatedSvg}---\n`);
-      return;
+      console.error(
+        `Template ${filename}: ${error}\n` +
+          '  Generated untemplated SVG:\n' +
+          `---\n${untemplatedSvg}---\n`
+      )
+      return
     }
 
     // Substitute dot code back.
-    let svg = data;
-    const unmappedKeys = [];
+    let svg = data
+    const unmappedKeys = []
     mapping.forEach(function(value, key) {
-      let keySubstituted = false;
+      let keySubstituted = false
       svg = svg.replace(RegExp(key, 'g'), function() {
-        keySubstituted = true;
-        return value;
-      });
+        keySubstituted = true
+        return value
+      })
       if (!keySubstituted) {
-        unmappedKeys.push(key);
+        unmappedKeys.push(key)
       }
-    });
+    })
     if (unmappedKeys.length > 0) {
-      console.error(`Template ${filename} has unmapped keys ` +
-        `${unmappedKeys.join(', ')}.\n` +
-        '  Generated untemplated SVG:\n' +
-        `---\n${untemplatedSvg}\n---\n` +
-        '  Generated template:\n' +
-        `---\n${svg}\n---\n`);
-      return;
+      console.error(
+        `Template ${filename} has unmapped keys ` +
+          `${unmappedKeys.join(', ')}.\n` +
+          '  Generated untemplated SVG:\n' +
+          `---\n${untemplatedSvg}\n---\n` +
+          '  Generated template:\n' +
+          `---\n${svg}\n---\n`
+      )
+      return
     }
 
-    templates[style + '-' + extension] = dot.template(svg);
+    templates[style + '-' + extension] = dot.template(svg)
   }
-});
+})
 
 function escapeXml(s) {
   if (s === undefined || typeof s !== 'string') {
-    return undefined;
+    return undefined
   } else {
-    return s.replace(/&/g, '&amp;')
-            .replace(/</g, '&lt;')
-            .replace(/>/g, '&gt;')
-            .replace(/"/g, '&quot;')
-            .replace(/'/g, '&apos;');
+    return s
+      .replace(/&/g, '&amp;')
+      .replace(/</g, '&lt;')
+      .replace(/>/g, '&gt;')
+      .replace(/"/g, '&quot;')
+      .replace(/'/g, '&apos;')
   }
 }
 
 function capitalize(s) {
-  return s.charAt(0).toUpperCase() + s.slice(1);
+  return s.charAt(0).toUpperCase() + s.slice(1)
 }
 
 // check if colorA/B is a colorscheme else check if it's a valid css3 color else return undefined and let the badge assign the default color
 function assignColor(color = '', colorschemeType = 'colorB') {
   if (definedColorschemes[color] !== undefined) {
-    return definedColorschemes[color][colorschemeType] || undefined;
+    return definedColorschemes[color][colorschemeType] || undefined
   } else if (isCSSColor(color)) {
-    return color;
+    return color
   } else {
-    return undefined;
+    return undefined
   }
 }
 
-const definedColorschemes = require(path.join(__dirname, 'colorscheme.json'));
+const definedColorschemes = require(path.join(__dirname, 'colorscheme.json'))
 
 // Inject the measurer to avoid placing any persistent state in this module.
-function makeBadge (measurer, {
-  format,
-  template,
-  text,
-  colorscheme,
-  colorA,
-  colorB,
-  logo,
-  logoPosition,
-  logoWidth,
-  links = ['', ''],
-}) {
+function makeBadge(
+  measurer,
+  {
+    format,
+    template,
+    text,
+    colorscheme,
+    colorA,
+    colorB,
+    logo,
+    logoPosition,
+    logoWidth,
+    links = ['', ''],
+  }
+) {
   // String coercion.
-  text = text.map(value => '' + value);
+  text = text.map(value => '' + value)
 
   if (format !== 'json') {
-    format = 'svg';
+    format = 'svg'
   }
 
   if (!(`${template}-${format}` in templates)) {
-    template = format === 'svg' ? 'flat' : 'default';
+    template = format === 'svg' ? 'flat' : 'default'
   }
   if (template.startsWith('popout')) {
-    if (logo){
-      logoPosition = (logoPosition <= 10 && logoPosition >= -10) ? logoPosition : 0;
-      logoWidth = +logoWidth || 32;
+    if (logo) {
+      logoPosition =
+        logoPosition <= 10 && logoPosition >= -10 ? logoPosition : 0
+      logoWidth = +logoWidth || 32
     } else {
-      template = template.replace('popout', 'flat');
+      template = template.replace('popout', 'flat')
     }
   }
   if (template === 'social') {
-    text[0] = capitalize(text[0]);
+    text[0] = capitalize(text[0])
   } else if (template === 'for-the-badge') {
-    text = text.map(value => value.toUpperCase());
+    text = text.map(value => value.toUpperCase())
   }
 
   // colorA/B have a higher priority than colorscheme
-  colorA = colorA || colorscheme || undefined;
-  colorB = colorB || colorscheme || undefined;
-  colorA = assignColor(colorA, 'colorA');
-  colorB = assignColor(colorB, 'colorB');
+  colorA = colorA || colorscheme || undefined
+  colorB = colorB || colorscheme || undefined
+  colorA = assignColor(colorA, 'colorA')
+  colorB = assignColor(colorB, 'colorB')
 
-  const [left, right] = text;
-  let leftWidth = badgeKeyWidthCache.get(left);
+  const [left, right] = text
+  let leftWidth = badgeKeyWidthCache.get(left)
   if (leftWidth === undefined) {
-    leftWidth = measurer.widthOf(left) | 0;
+    leftWidth = measurer.widthOf(left) | 0
     // Increase chances of pixel grid alignment.
-    if (leftWidth % 2 === 0) { leftWidth++; }
-    badgeKeyWidthCache.set(left, leftWidth);
+    if (leftWidth % 2 === 0) {
+      leftWidth++
+    }
+    badgeKeyWidthCache.set(left, leftWidth)
   }
-  let rightWidth = measurer.widthOf(right) | 0;
+  let rightWidth = measurer.widthOf(right) | 0
   // Increase chances of pixel grid alignment.
-  if (rightWidth % 2 === 0) { rightWidth++; }
+  if (rightWidth % 2 === 0) {
+    rightWidth++
+  }
 
-  logoWidth = +logoWidth || (logo ? 14 : 0);
+  logoWidth = +logoWidth || (logo ? 14 : 0)
 
-  let logoPadding;
+  let logoPadding
   if (left.length === 0) {
-    logoPadding = 0;
+    logoPadding = 0
   } else {
-    logoPadding = logo ? 3 : 0;
+    logoPadding = logo ? 3 : 0
   }
 
   const context = {
     text: [left, right],
     escapedText: text.map(escapeXml),
-    widths: [
-      leftWidth + 10 + logoWidth + logoPadding,
-      rightWidth + 10,
-    ],
+    widths: [leftWidth + 10 + logoWidth + logoPadding, rightWidth + 10],
     links: links.map(escapeXml),
     logo,
     logoPosition,
@@ -179,12 +192,12 @@ function makeBadge (measurer, {
     colorA,
     colorB,
     escapeXml,
-  };
+  }
 
-  const templateFn = templates[`${template}-${format}`];
+  const templateFn = templates[`${template}-${format}`]
 
   // The call to template() can raise an exception.
-  return templateFn(context);
+  return templateFn(context)
 }
 
 module.exports = {
@@ -192,4 +205,4 @@ module.exports = {
   makeMakeBadgeFn: measurer => data => makeBadge(measurer, data),
   // Expose for testing.
   _badgeKeyWidthCache: badgeKeyWidthCache,
-};
+}
diff --git a/lib/make-badge.spec.js b/lib/make-badge.spec.js
index 898e2eebff4dd1ff956639451a8c668f05da4220..658f0cb4a14d537de83242eab5d189f40a02e0ac 100644
--- a/lib/make-badge.spec.js
+++ b/lib/make-badge.spec.js
@@ -1,43 +1,50 @@
-'use strict';
-
-const { test, given, forCases } = require('sazerac');
-const { expect } = require('chai');
-const snapshot = require('snap-shot-it');
-const { _badgeKeyWidthCache } = require('./make-badge');
-const isSvg = require('is-svg');
-const testHelpers = require('./make-badge-test-helpers');
-const colorschemes = require('./colorscheme.json');
-
-const makeBadge = testHelpers.makeBadge();
-
-function testColor(color = ''){
-  return JSON.parse(makeBadge({ text: ['name', 'Bob'], colorB: color, format: 'json', template: '_shields_test' })).colorB;
+'use strict'
+
+const { test, given, forCases } = require('sazerac')
+const { expect } = require('chai')
+const snapshot = require('snap-shot-it')
+const { _badgeKeyWidthCache } = require('./make-badge')
+const isSvg = require('is-svg')
+const testHelpers = require('./make-badge-test-helpers')
+const colorschemes = require('./colorscheme.json')
+
+const makeBadge = testHelpers.makeBadge()
+
+function testColor(color = '') {
+  return JSON.parse(
+    makeBadge({
+      text: ['name', 'Bob'],
+      colorB: color,
+      format: 'json',
+      template: '_shields_test',
+    })
+  ).colorB
 }
 
 describe('The badge generator', () => {
   beforeEach(() => {
-    _badgeKeyWidthCache.clear();
-  });
+    _badgeKeyWidthCache.clear()
+  })
 
   describe('color test', () => {
     test(testColor, () => {
       // valid hex
-      given('#4c1').expect('#4c1');
-      given('#4C1').expect('#4C1');
-      given('#abc123').expect('#abc123');
-      given('#ABC123').expect('#ABC123');
+      given('#4c1').expect('#4c1')
+      given('#4C1').expect('#4C1')
+      given('#abc123').expect('#abc123')
+      given('#ABC123').expect('#ABC123')
       // valid rgb(a)
-      given('rgb(0,128,255)').expect('rgb(0,128,255)');
-      given('rgba(0,128,255,0)').expect('rgba(0,128,255,0)');
+      given('rgb(0,128,255)').expect('rgb(0,128,255)')
+      given('rgba(0,128,255,0)').expect('rgba(0,128,255,0)')
       // valid hsl(a)
-      given('hsl(100, 56%, 10%)').expect('hsl(100, 56%, 10%)');
-      given('hsla(25,20%,0%,0.1)').expect('hsla(25,20%,0%,0.1)');
+      given('hsl(100, 56%, 10%)').expect('hsl(100, 56%, 10%)')
+      given('hsla(25,20%,0%,0.1)').expect('hsla(25,20%,0%,0.1)')
       // either a css named color or colorscheme
-      given('papayawhip').expect('papayawhip');
-      given('red').expect(colorschemes['red'].colorB);
-      given('green').expect(colorschemes['green'].colorB);
-      given('blue').expect(colorschemes['blue'].colorB);
-      given('yellow').expect(colorschemes['yellow'].colorB);
+      given('papayawhip').expect('papayawhip')
+      given('red').expect(colorschemes['red'].colorB)
+      given('green').expect(colorschemes['green'].colorB)
+      given('blue').expect(colorschemes['blue'].colorB)
+      given('yellow').expect(colorschemes['yellow'].colorB)
 
       forCases(
         // invalid hex
@@ -56,96 +63,158 @@ describe('The badge generator', () => {
         given('bluish'),
         given('almostred'),
         given('brightmaroon'),
-        given('cactus'),
+        given('cactus')
       ).expect(undefined)
-    });
-  });
+    })
+  })
 
   describe('SVG', () => {
     it('should produce SVG', () => {
-      const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' });
+      const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' })
       expect(svg)
         .to.satisfy(isSvg)
         .and.to.include('cactus')
-        .and.to.include('grown');
-    });
+        .and.to.include('grown')
+    })
 
     it('should always produce the same SVG (unless we have changed something!)', () => {
-      const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' });
-      snapshot(svg);
-    });
+      const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' })
+      snapshot(svg)
+    })
 
     it('should cache width of badge key', () => {
-      makeBadge({ text: ['cached', 'not-cached'], format: 'svg' });
-      expect(_badgeKeyWidthCache.cache).to.have.keys('cached');
-    });
-  });
+      makeBadge({ text: ['cached', 'not-cached'], format: 'svg' })
+      expect(_badgeKeyWidthCache.cache).to.have.keys('cached')
+    })
+  })
 
   describe('JSON', () => {
     it('should always produce the same JSON (unless we have changed something!)', () => {
-      const json = makeBadge({ text: ['cactus', 'grown'], format: 'json' });
-      snapshot(json);
-    });
+      const json = makeBadge({ text: ['cactus', 'grown'], format: 'json' })
+      snapshot(json)
+    })
 
     it('should replace unknown json template with "default"', () => {
-      const jsonBadgeWithUnknownStyle = makeBadge({ text: ['name', 'Bob'], format: 'json', template: 'unknown_style' });
-      const jsonBadgeWithDefaultStyle = makeBadge({ text: ['name', 'Bob'], format: 'json', template: 'default' });
-      expect(jsonBadgeWithUnknownStyle).to.equal(jsonBadgeWithDefaultStyle);
-      expect(JSON.parse(jsonBadgeWithUnknownStyle)).to.deep.equal({name: "name", value: "Bob"})
-    });
+      const jsonBadgeWithUnknownStyle = makeBadge({
+        text: ['name', 'Bob'],
+        format: 'json',
+        template: 'unknown_style',
+      })
+      const jsonBadgeWithDefaultStyle = makeBadge({
+        text: ['name', 'Bob'],
+        format: 'json',
+        template: 'default',
+      })
+      expect(jsonBadgeWithUnknownStyle).to.equal(jsonBadgeWithDefaultStyle)
+      expect(JSON.parse(jsonBadgeWithUnknownStyle)).to.deep.equal({
+        name: 'name',
+        value: 'Bob',
+      })
+    })
 
     it('should replace unknown svg template with "flat"', () => {
-      const jsonBadgeWithUnknownStyle = makeBadge({ text: ['name', 'Bob'], format: 'svg', template: 'unknown_style' });
-      const jsonBadgeWithDefaultStyle = makeBadge({ text: ['name', 'Bob'], format: 'svg', template: 'flat' });
-      expect(jsonBadgeWithUnknownStyle).to.equal(jsonBadgeWithDefaultStyle)
-        .and.to.satisfy(isSvg);
-    });
-  });
+      const jsonBadgeWithUnknownStyle = makeBadge({
+        text: ['name', 'Bob'],
+        format: 'svg',
+        template: 'unknown_style',
+      })
+      const jsonBadgeWithDefaultStyle = makeBadge({
+        text: ['name', 'Bob'],
+        format: 'svg',
+        template: 'flat',
+      })
+      expect(jsonBadgeWithUnknownStyle)
+        .to.equal(jsonBadgeWithDefaultStyle)
+        .and.to.satisfy(isSvg)
+    })
+  })
 
   describe('"for-the-badge" template badge generation', () => {
-     // https://github.com/badges/shields/issues/1280
+    // https://github.com/badges/shields/issues/1280
     it('numbers should produce a string', () => {
-      const svg = makeBadge({ text: [1998, 1999], format: 'svg', template: 'for-the-badge' });
-      expect(svg).to.include('1998').and.to.include('1999');
-    });
+      const svg = makeBadge({
+        text: [1998, 1999],
+        format: 'svg',
+        template: 'for-the-badge',
+      })
+      expect(svg)
+        .to.include('1998')
+        .and.to.include('1999')
+    })
 
     it('lowercase/mixedcase string should produce uppercase string', () => {
-      const svg = makeBadge({ text: ["Label", "1 string"], format: 'svg', template: 'for-the-badge' });
-      expect(svg).to.include('LABEL').and.to.include('1 STRING');
-    });
-  });
+      const svg = makeBadge({
+        text: ['Label', '1 string'],
+        format: 'svg',
+        template: 'for-the-badge',
+      })
+      expect(svg)
+        .to.include('LABEL')
+        .and.to.include('1 STRING')
+    })
+  })
 
   describe('"social" template badge generation', () => {
     it('should produce capitalized string for badge key', () => {
-      const svg = makeBadge({ text: ["some-key", "some-value"], format: 'svg', template: 'social' });
-      expect(svg).to.include('Some-key').and.to.include('some-value');
-    });
+      const svg = makeBadge({
+        text: ['some-key', 'some-value'],
+        format: 'svg',
+        template: 'social',
+      })
+      expect(svg)
+        .to.include('Some-key')
+        .and.to.include('some-value')
+    })
 
-     // https://github.com/badges/shields/issues/1606
+    // https://github.com/badges/shields/issues/1606
     it('should handle empty strings used as badge keys', () => {
-      const svg = makeBadge({ text: ["", "some-value"], format: 'json', template: 'social' });
-      expect(svg).to.include('""').and.to.include('some-value');
-    });
-  });
+      const svg = makeBadge({
+        text: ['', 'some-value'],
+        format: 'json',
+        template: 'social',
+      })
+      expect(svg)
+        .to.include('""')
+        .and.to.include('some-value')
+    })
+  })
   describe('badges with logos should always produce the same badge', () => {
     it('shields GitHub logo default color (#333333)', () => {
-      const svg = makeBadge({ text: ['label', 'message'], format: 'svg', logo: 'github' });
-      snapshot(svg);
-    });
+      const svg = makeBadge({
+        text: ['label', 'message'],
+        format: 'svg',
+        logo: 'github',
+      })
+      snapshot(svg)
+    })
 
     it('shields GitHub logo custom color (whitesmoke)', () => {
-      const svg = makeBadge({ text: ['label', 'message'], format: 'svg', logo: 'github', logoColor: 'whitesmoke' });
-      snapshot(svg);
-    });
+      const svg = makeBadge({
+        text: ['label', 'message'],
+        format: 'svg',
+        logo: 'github',
+        logoColor: 'whitesmoke',
+      })
+      snapshot(svg)
+    })
 
     it('simple-icons javascript logo default color (#F7DF1E)', () => {
-      const svg = makeBadge({ text: ['label', 'message'], format: 'svg', logo: 'javascript' });
-      snapshot(svg);
-    });
+      const svg = makeBadge({
+        text: ['label', 'message'],
+        format: 'svg',
+        logo: 'javascript',
+      })
+      snapshot(svg)
+    })
 
     it('simple-icons javascript logo custom color (rgba(46,204,113,0.8))', () => {
-      const svg = makeBadge({ text: ['label', 'message'], format: 'svg', logo: 'javascript', logoColor: 'rgba(46,204,113,0.8)' });
-      snapshot(svg);
-    });
-  });
-});
+      const svg = makeBadge({
+        text: ['label', 'message'],
+        format: 'svg',
+        logo: 'javascript',
+        logoColor: 'rgba(46,204,113,0.8)',
+      })
+      snapshot(svg)
+    })
+  })
+})
diff --git a/lib/nexus-version.js b/lib/nexus-version.js
index 3f3a51d3068136546ead79801403af4904270efa..f612b1e59cec8e76167a188882deb00b6baa96c4 100644
--- a/lib/nexus-version.js
+++ b/lib/nexus-version.js
@@ -1,10 +1,10 @@
-'use strict';
+'use strict'
 
 function isSnapshotVersion(version) {
-  const pattern = /(\d+\.)*\d-SNAPSHOT/;
-  return version && version.match(pattern);
+  const pattern = /(\d+\.)*\d-SNAPSHOT/
+  return version && version.match(pattern)
 }
 
 module.exports = {
-  isSnapshotVersion
-};
+  isSnapshotVersion,
+}
diff --git a/lib/nodeify-sync.js b/lib/nodeify-sync.js
index a5aa04ae52023ec958ea5f6aed73284f45f25afb..82786faab112eba1ea4076dfb65bc5bfccdfaac4 100644
--- a/lib/nodeify-sync.js
+++ b/lib/nodeify-sync.js
@@ -1,17 +1,17 @@
-'use strict';
+'use strict'
 
 // Execute a synchronous block and invoke a standard error-first callback with
 // the result.
 function nodeifySync(resultFn, callback) {
-  let result, error;
+  let result, error
 
   try {
-    result = resultFn();
+    result = resultFn()
   } catch (e) {
-    error = e;
+    error = e
   }
 
-  callback(error, result);
+  callback(error, result)
 }
 
-module.exports = nodeifySync;
+module.exports = nodeifySync
diff --git a/lib/nodeify-sync.spec.js b/lib/nodeify-sync.spec.js
index 431c5360e5c0af06ce6ff3a956f08a1540d9da9c..f288b23fb7b928da8d15283fb6dddfcc400f137c 100644
--- a/lib/nodeify-sync.spec.js
+++ b/lib/nodeify-sync.spec.js
@@ -1,24 +1,32 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const nodeifySync = require('./nodeify-sync');
+const { expect } = require('chai')
+const nodeifySync = require('./nodeify-sync')
 
 describe('nodeifySync()', function() {
   it('Should return the result via the callback', function(done) {
-    const exampleValue = {};
-    nodeifySync(() => exampleValue, (err, result) => {
-      expect(err).to.be.undefined;
-      expect(result).to.equal(exampleValue);
-      done();
-    });
-  });
+    const exampleValue = {}
+    nodeifySync(
+      () => exampleValue,
+      (err, result) => {
+        expect(err).to.be.undefined
+        expect(result).to.equal(exampleValue)
+        done()
+      }
+    )
+  })
 
   it('Should catch an error and return it via the callback', function(done) {
-    const exampleError = Error('This is my error!');
-    nodeifySync(() => { throw exampleError; }, (err, result) => {
-      expect(err).to.equal(exampleError);
-      expect(result).to.be.undefined;
-      done();
-    });
-  });
-});
+    const exampleError = Error('This is my error!')
+    nodeifySync(
+      () => {
+        throw exampleError
+      },
+      (err, result) => {
+        expect(err).to.equal(exampleError)
+        expect(result).to.be.undefined
+        done()
+      }
+    )
+  })
+})
diff --git a/lib/nuget-provider.js b/lib/nuget-provider.js
index 549cbbdf7da08e9017ee92ad3cadc075e542617d..4879bd4d10e48db5802e7fcb2cab752a05a7918c 100644
--- a/lib/nuget-provider.js
+++ b/lib/nuget-provider.js
@@ -1,295 +1,329 @@
-'use strict';
+'use strict'
 
-const { downloadCount: downloadCountColor } = require('./color-formatters');
-const { makeBadgeData: getBadgeData } = require('./badge-data');
-const { metric } = require('./text-formatters');
-const { regularUpdate } = require('./regular-update');
+const { downloadCount: downloadCountColor } = require('./color-formatters')
+const { makeBadgeData: getBadgeData } = require('./badge-data')
+const { metric } = require('./text-formatters')
+const { regularUpdate } = require('./regular-update')
 
 function mapNugetFeedv2({ camp, cache }, pattern, offset, getInfo) {
-  const vRegex = new RegExp('^\\/' + pattern + '\\/v\\/(.*)\\.(svg|png|gif|jpg|json)$');
-  const vPreRegex = new RegExp('^\\/' + pattern + '\\/vpre\\/(.*)\\.(svg|png|gif|jpg|json)$');
-  const dtRegex = new RegExp('^\\/' + pattern + '\\/dt\\/(.*)\\.(svg|png|gif|jpg|json)$');
+  const vRegex = new RegExp(
+    '^\\/' + pattern + '\\/v\\/(.*)\\.(svg|png|gif|jpg|json)$'
+  )
+  const vPreRegex = new RegExp(
+    '^\\/' + pattern + '\\/vpre\\/(.*)\\.(svg|png|gif|jpg|json)$'
+  )
+  const dtRegex = new RegExp(
+    '^\\/' + pattern + '\\/dt\\/(.*)\\.(svg|png|gif|jpg|json)$'
+  )
 
   function getNugetPackage(apiUrl, id, includePre, request, done) {
-    const filter = includePre ?
-      'Id eq \'' + id + '\' and IsAbsoluteLatestVersion eq true' :
-      'Id eq \'' + id + '\' and IsLatestVersion eq true';
-    const reqUrl = apiUrl + '/Packages()?$filter=' + encodeURIComponent(filter);
-    request(reqUrl,
-    { headers: { 'Accept': 'application/atom+json,application/json' } },
-    function(err, res, buffer) {
-      if (err != null) {
-        done(new Error('inaccessible'));
-        return;
-      }
+    const filter = includePre
+      ? "Id eq '" + id + "' and IsAbsoluteLatestVersion eq true"
+      : "Id eq '" + id + "' and IsLatestVersion eq true"
+    const reqUrl = apiUrl + '/Packages()?$filter=' + encodeURIComponent(filter)
+    request(
+      reqUrl,
+      { headers: { Accept: 'application/atom+json,application/json' } },
+      function(err, res, buffer) {
+        if (err != null) {
+          done(new Error('inaccessible'))
+          return
+        }
 
-      try {
-        const data = JSON.parse(buffer);
-        const result = data.d.results[0];
-        if (result == null) {
-          if (includePre === null) {
-            getNugetPackage(apiUrl, id, true, request, done);
+        try {
+          const data = JSON.parse(buffer)
+          const result = data.d.results[0]
+          if (result == null) {
+            if (includePre === null) {
+              getNugetPackage(apiUrl, id, true, request, done)
+            } else {
+              done(new Error('not found'))
+            }
           } else {
-            done(new Error('not found'));
+            done(null, result)
           }
-        } else {
-          done(null, result);
+        } catch (e) {
+          done(new Error('invalid'))
         }
-      } catch (e) {
-        done(new Error('invalid'));
       }
-    });
+    )
   }
 
-  camp.route(vRegex,
-  cache(function(data, match, sendBadge, request) {
-    const info = getInfo(match);
-    const site = info.site;  // eg, `Chocolatey`, or `YoloDev`
-    const repo = match[offset + 1];  // eg, `Nuget.Core`.
-    const format = match[offset + 2];
-    const apiUrl = info.feed;
-    const badgeData = getBadgeData(site, data);
-    getNugetPackage(apiUrl, repo, null, request, function(err, data) {
-      if (err != null) {
-        badgeData.text[1] = err.message;
-        sendBadge(format, badgeData);
-        return;
-      }
-      const version = data.NormalizedVersion || data.Version;
-      badgeData.text[1] = 'v' + version;
-      if (version.indexOf('-') !== -1) {
-        badgeData.colorscheme = 'yellow';
-      } else if (version[0] === '0') {
-        badgeData.colorscheme = 'orange';
-      } else {
-        badgeData.colorscheme = 'blue';
-      }
-      sendBadge(format, badgeData);
-    });
-  }));
+  camp.route(
+    vRegex,
+    cache(function(data, match, sendBadge, request) {
+      const info = getInfo(match)
+      const site = info.site // eg, `Chocolatey`, or `YoloDev`
+      const repo = match[offset + 1] // eg, `Nuget.Core`.
+      const format = match[offset + 2]
+      const apiUrl = info.feed
+      const badgeData = getBadgeData(site, data)
+      getNugetPackage(apiUrl, repo, null, request, function(err, data) {
+        if (err != null) {
+          badgeData.text[1] = err.message
+          sendBadge(format, badgeData)
+          return
+        }
+        const version = data.NormalizedVersion || data.Version
+        badgeData.text[1] = 'v' + version
+        if (version.indexOf('-') !== -1) {
+          badgeData.colorscheme = 'yellow'
+        } else if (version[0] === '0') {
+          badgeData.colorscheme = 'orange'
+        } else {
+          badgeData.colorscheme = 'blue'
+        }
+        sendBadge(format, badgeData)
+      })
+    })
+  )
 
-  camp.route(vPreRegex,
-  cache(function(data, match, sendBadge, request) {
-    const info = getInfo(match);
-    const site = info.site;  // eg, `Chocolatey`, or `YoloDev`
-    const repo = match[offset + 1];  // eg, `Nuget.Core`.
-    const format = match[offset + 2];
-    const apiUrl = info.feed;
-    const badgeData = getBadgeData(site, data);
-    getNugetPackage(apiUrl, repo, true, request, function(err, data) {
-      if (err != null) {
-        badgeData.text[1] = err.message;
-        sendBadge(format, badgeData);
-        return;
-      }
-      const version = data.NormalizedVersion || data.Version;
-      badgeData.text[1] = 'v' + version;
-      if (version.indexOf('-') !== -1) {
-        badgeData.colorscheme = 'yellow';
-      } else if (version[0] === '0') {
-        badgeData.colorscheme = 'orange';
-      } else {
-        badgeData.colorscheme = 'blue';
-      }
-      sendBadge(format, badgeData);
-    });
-  }));
+  camp.route(
+    vPreRegex,
+    cache(function(data, match, sendBadge, request) {
+      const info = getInfo(match)
+      const site = info.site // eg, `Chocolatey`, or `YoloDev`
+      const repo = match[offset + 1] // eg, `Nuget.Core`.
+      const format = match[offset + 2]
+      const apiUrl = info.feed
+      const badgeData = getBadgeData(site, data)
+      getNugetPackage(apiUrl, repo, true, request, function(err, data) {
+        if (err != null) {
+          badgeData.text[1] = err.message
+          sendBadge(format, badgeData)
+          return
+        }
+        const version = data.NormalizedVersion || data.Version
+        badgeData.text[1] = 'v' + version
+        if (version.indexOf('-') !== -1) {
+          badgeData.colorscheme = 'yellow'
+        } else if (version[0] === '0') {
+          badgeData.colorscheme = 'orange'
+        } else {
+          badgeData.colorscheme = 'blue'
+        }
+        sendBadge(format, badgeData)
+      })
+    })
+  )
 
-  camp.route(dtRegex,
-  cache(function(data, match, sendBadge, request) {
-    const info = getInfo(match);
-    const repo = match[offset+ 1];  // eg, `Nuget.Core`.
-    const format = match[offset + 2];
-    const apiUrl = info.feed;
-    const badgeData = getBadgeData('downloads', data);
-    getNugetPackage(apiUrl, repo, null, request, function(err, data) {
-      if (err != null) {
-        badgeData.text[1] = err.message;
-        sendBadge(format, badgeData);
-        return;
-      }
-      const downloads = data.DownloadCount;
-      badgeData.text[1] = metric(downloads);
-      badgeData.colorscheme = downloadCountColor(downloads);
-      sendBadge(format, badgeData);
-    });
-  }));
+  camp.route(
+    dtRegex,
+    cache(function(data, match, sendBadge, request) {
+      const info = getInfo(match)
+      const repo = match[offset + 1] // eg, `Nuget.Core`.
+      const format = match[offset + 2]
+      const apiUrl = info.feed
+      const badgeData = getBadgeData('downloads', data)
+      getNugetPackage(apiUrl, repo, null, request, function(err, data) {
+        if (err != null) {
+          badgeData.text[1] = err.message
+          sendBadge(format, badgeData)
+          return
+        }
+        const downloads = data.DownloadCount
+        badgeData.text[1] = metric(downloads)
+        badgeData.colorscheme = downloadCountColor(downloads)
+        sendBadge(format, badgeData)
+      })
+    })
+  )
 }
 
 function mapNugetFeed({ camp, cache }, pattern, offset, getInfo) {
-  const vRegex = new RegExp('^\\/' + pattern + '\\/v\\/(.*)\\.(svg|png|gif|jpg|json)$');
-  const vPreRegex = new RegExp('^\\/' + pattern + '\\/vpre\\/(.*)\\.(svg|png|gif|jpg|json)$');
-  const dtRegex = new RegExp('^\\/' + pattern + '\\/dt\\/(.*)\\.(svg|png|gif|jpg|json)$');
+  const vRegex = new RegExp(
+    '^\\/' + pattern + '\\/v\\/(.*)\\.(svg|png|gif|jpg|json)$'
+  )
+  const vPreRegex = new RegExp(
+    '^\\/' + pattern + '\\/vpre\\/(.*)\\.(svg|png|gif|jpg|json)$'
+  )
+  const dtRegex = new RegExp(
+    '^\\/' + pattern + '\\/dt\\/(.*)\\.(svg|png|gif|jpg|json)$'
+  )
 
   function getNugetData(apiUrl, id, request, done) {
     // get service index document
 
-    regularUpdate({
-      url: apiUrl + '/index.json',
-      // The endpoint changes once per year (ie, a period of n = 1 year).
-      // We minimize the users' waiting time for information.
-      // With l = latency to fetch the endpoint and x = endpoint update period
-      // both in years, the yearly number of queries for the endpoint are 1/x,
-      // and when the endpoint changes, we wait for up to x years to get the
-      // right endpoint.
-      // So the waiting time within n years is n*l/x + x years, for which a
-      // derivation yields an optimum at x = sqrt(n*l), roughly 42 minutes.
-      intervalMillis: 42 * 60 * 1000,
-      json: false,
-      scraper: function(data) { return data; },
-    }, (err, buf) => {
+    regularUpdate(
+      {
+        url: apiUrl + '/index.json',
+        // The endpoint changes once per year (ie, a period of n = 1 year).
+        // We minimize the users' waiting time for information.
+        // With l = latency to fetch the endpoint and x = endpoint update period
+        // both in years, the yearly number of queries for the endpoint are 1/x,
+        // and when the endpoint changes, we wait for up to x years to get the
+        // right endpoint.
+        // So the waiting time within n years is n*l/x + x years, for which a
+        // derivation yields an optimum at x = sqrt(n*l), roughly 42 minutes.
+        intervalMillis: 42 * 60 * 1000,
+        json: false,
+        scraper: function(data) {
+          return data
+        },
+      },
+      (err, buf) => {
         if (err != null) {
-          done(new Error('inaccessible'));
-          return;
+          done(new Error('inaccessible'))
+          return
         }
 
         try {
           const searchQueryResources = JSON.parse(buf).resources.filter(
             resource => resource['@type'] === 'SearchQueryService'
-          );
+          )
           // query autocomplete service
-          const randomEndpointIdx = Math.floor(Math.random() * searchQueryResources.length);
-          const reqUrl = searchQueryResources[randomEndpointIdx]['@id']
-            + '?q=packageid:' + encodeURIComponent(id.toLowerCase()) // NuGet package id (lowercase)
-            + '&prerelease=true';                                    // Include prerelease versions?
+          const randomEndpointIdx = Math.floor(
+            Math.random() * searchQueryResources.length
+          )
+          const reqUrl =
+            searchQueryResources[randomEndpointIdx]['@id'] +
+            '?q=packageid:' +
+            encodeURIComponent(id.toLowerCase()) + // NuGet package id (lowercase)
+            '&prerelease=true' // Include prerelease versions?
 
           request(reqUrl, (err, res, buffer) => {
             if (err != null) {
-              done(new Error('inaccessible'));
-              return;
+              done(new Error('inaccessible'))
+              return
             }
 
             try {
-              const data = JSON.parse(buffer);
+              const data = JSON.parse(buffer)
               if (!Array.isArray(data.data) || data.data.length !== 1) {
-                done(new Error('not found'));
-                return;
+                done(new Error('not found'))
+                return
               }
-              done(null, data.data[0]);
+              done(null, data.data[0])
             } catch (e) {
-              done(new Error('invalid'));
+              done(new Error('invalid'))
             }
-          });
-
+          })
         } catch (e) {
-          done(new Error('invalid'));
+          done(new Error('invalid'))
         }
-      });
+      }
+    )
   }
 
   function getNugetVersion(apiUrl, id, includePre, request, done) {
     getNugetData(apiUrl, id, request, function(err, data) {
       if (err) {
-        done(err);
-        return;
+        done(err)
+        return
       }
-      let versions = data.versions || [];
+      let versions = data.versions || []
       if (!includePre) {
         // Remove prerelease versions.
         const filteredVersions = versions.filter(function(version) {
-          return !/-/.test(version.version);
-        });
+          return !/-/.test(version.version)
+        })
         if (filteredVersions.length > 0) {
-          versions = filteredVersions;
+          versions = filteredVersions
         }
       }
-      const lastVersion = versions[versions.length - 1];
-      done(null, lastVersion.version);
-    });
+      const lastVersion = versions[versions.length - 1]
+      done(null, lastVersion.version)
+    })
   }
 
-  camp.route(vRegex,
-  cache(function(data, match, sendBadge, request) {
-    const info = getInfo(match);
-    const site = info.site;  // eg, `Chocolatey`, or `YoloDev`
-    const repo = match[offset + 1];  // eg, `Nuget.Core`.
-    const format = match[offset + 2];
-    const apiUrl = info.feed;
-    const badgeData = getBadgeData(site, data);
-    getNugetVersion(apiUrl, repo, false, request, function(err, version) {
-      if (err != null) {
-        badgeData.text[1] = err.message;
-        sendBadge(format, badgeData);
-        return;
-      }
-      try {
-        badgeData.text[1] = 'v' + version;
-        if (version.indexOf('-') !== -1) {
-          badgeData.colorscheme = 'yellow';
-        } else if (version[0] === '0') {
-          badgeData.colorscheme = 'orange';
-        } else {
-          badgeData.colorscheme = 'blue';
+  camp.route(
+    vRegex,
+    cache(function(data, match, sendBadge, request) {
+      const info = getInfo(match)
+      const site = info.site // eg, `Chocolatey`, or `YoloDev`
+      const repo = match[offset + 1] // eg, `Nuget.Core`.
+      const format = match[offset + 2]
+      const apiUrl = info.feed
+      const badgeData = getBadgeData(site, data)
+      getNugetVersion(apiUrl, repo, false, request, function(err, version) {
+        if (err != null) {
+          badgeData.text[1] = err.message
+          sendBadge(format, badgeData)
+          return
         }
-        sendBadge(format, badgeData);
-      } catch(e) {
-        badgeData.text[1] = 'invalid';
-        sendBadge(format, badgeData);
-      }
-    });
-  }));
-
-  camp.route(vPreRegex,
-  cache(function(data, match, sendBadge, request) {
-    const info = getInfo(match);
-    const site = info.site;  // eg, `Chocolatey`, or `YoloDev`
-    const repo = match[offset + 1];  // eg, `Nuget.Core`.
-    const format = match[offset + 2];
-    const apiUrl = info.feed;
-    const badgeData = getBadgeData(site, data);
-    getNugetVersion(apiUrl, repo, true, request, function(err, version) {
-      if (err != null) {
-        badgeData.text[1] = err.message;
-        sendBadge(format, badgeData);
-        return;
-      }
-      try {
-        badgeData.text[1] = 'v' + version;
-        if (version.indexOf('-') !== -1) {
-          badgeData.colorscheme = 'yellow';
-        } else if (version[0] === '0') {
-          badgeData.colorscheme = 'orange';
-        } else {
-          badgeData.colorscheme = 'blue';
+        try {
+          badgeData.text[1] = 'v' + version
+          if (version.indexOf('-') !== -1) {
+            badgeData.colorscheme = 'yellow'
+          } else if (version[0] === '0') {
+            badgeData.colorscheme = 'orange'
+          } else {
+            badgeData.colorscheme = 'blue'
+          }
+          sendBadge(format, badgeData)
+        } catch (e) {
+          badgeData.text[1] = 'invalid'
+          sendBadge(format, badgeData)
         }
-        sendBadge(format, badgeData);
-      } catch(e) {
-        badgeData.text[1] = 'invalid';
-        sendBadge(format, badgeData);
-      }
-    });
-  }));
+      })
+    })
+  )
 
+  camp.route(
+    vPreRegex,
+    cache(function(data, match, sendBadge, request) {
+      const info = getInfo(match)
+      const site = info.site // eg, `Chocolatey`, or `YoloDev`
+      const repo = match[offset + 1] // eg, `Nuget.Core`.
+      const format = match[offset + 2]
+      const apiUrl = info.feed
+      const badgeData = getBadgeData(site, data)
+      getNugetVersion(apiUrl, repo, true, request, function(err, version) {
+        if (err != null) {
+          badgeData.text[1] = err.message
+          sendBadge(format, badgeData)
+          return
+        }
+        try {
+          badgeData.text[1] = 'v' + version
+          if (version.indexOf('-') !== -1) {
+            badgeData.colorscheme = 'yellow'
+          } else if (version[0] === '0') {
+            badgeData.colorscheme = 'orange'
+          } else {
+            badgeData.colorscheme = 'blue'
+          }
+          sendBadge(format, badgeData)
+        } catch (e) {
+          badgeData.text[1] = 'invalid'
+          sendBadge(format, badgeData)
+        }
+      })
+    })
+  )
 
-  camp.route(dtRegex,
-  cache(function(data, match, sendBadge, request) {
-    const info = getInfo(match);
-    const repo = match[offset + 1];  // eg, `Nuget.Core`.
-    const format = match[offset + 2];
-    const apiUrl = info.feed;
-    const badgeData = getBadgeData('downloads', data);
-    getNugetData(apiUrl, repo, request, function(err, nugetData) {
-      if (err != null) {
-        badgeData.text[1] = err.message;
-        sendBadge(format, badgeData);
-        return;
-      }
-      try {
-        // Official NuGet server uses "totalDownloads" whereas MyGet uses
-        // "totaldownloads" (lowercase D). Ugh.
-        const downloads = nugetData.totalDownloads || nugetData.totaldownloads || 0;
-        badgeData.text[1] = metric(downloads);
-        badgeData.colorscheme = downloadCountColor(downloads);
-        sendBadge(format, badgeData);
-      } catch(e) {
-        badgeData.text[1] = 'invalid';
-        sendBadge(format, badgeData);
-      }
-    });
-  }));
+  camp.route(
+    dtRegex,
+    cache(function(data, match, sendBadge, request) {
+      const info = getInfo(match)
+      const repo = match[offset + 1] // eg, `Nuget.Core`.
+      const format = match[offset + 2]
+      const apiUrl = info.feed
+      const badgeData = getBadgeData('downloads', data)
+      getNugetData(apiUrl, repo, request, function(err, nugetData) {
+        if (err != null) {
+          badgeData.text[1] = err.message
+          sendBadge(format, badgeData)
+          return
+        }
+        try {
+          // Official NuGet server uses "totalDownloads" whereas MyGet uses
+          // "totaldownloads" (lowercase D). Ugh.
+          const downloads =
+            nugetData.totalDownloads || nugetData.totaldownloads || 0
+          badgeData.text[1] = metric(downloads)
+          badgeData.colorscheme = downloadCountColor(downloads)
+          sendBadge(format, badgeData)
+        } catch (e) {
+          badgeData.text[1] = 'invalid'
+          sendBadge(format, badgeData)
+        }
+      })
+    })
+  )
 }
 
 module.exports = {
   mapNugetFeedv2,
-  mapNugetFeed
-};
+  mapNugetFeed,
+}
diff --git a/lib/path-helpers.js b/lib/path-helpers.js
index 5dfb6dea3ec18d806c5c2ee1fb16ff8b51e30a2b..bc0d63f162f9a232ce847b8c5c87eac0c13ae7cf 100644
--- a/lib/path-helpers.js
+++ b/lib/path-helpers.js
@@ -1,24 +1,30 @@
-'use strict';
+'use strict'
 
 // Escapes `t` using the format specified in
 // <https://github.com/espadrine/gh-badges/issues/12#issuecomment-31518129>
 function escapeFormat(t) {
-  return t
-    // Inline single underscore.
-    .replace(/([^_])_([^_])/g, '$1 $2')
-    // Leading or trailing underscore.
-    .replace(/([^_])_$/, '$1 ').replace(/^_([^_])/, ' $1')
-    // Double underscore and double dash.
-    .replace(/__/g, '_').replace(/--/g, '-');
+  return (
+    t
+      // Inline single underscore.
+      .replace(/([^_])_([^_])/g, '$1 $2')
+      // Leading or trailing underscore.
+      .replace(/([^_])_$/, '$1 ')
+      .replace(/^_([^_])/, ' $1')
+      // Double underscore and double dash.
+      .replace(/__/g, '_')
+      .replace(/--/g, '-')
+  )
 }
 
 function escapeFormatSlashes(t) {
-  return escapeFormat(t)
-    // Double slash
-    .replace(/\/\//g, '/');
+  return (
+    escapeFormat(t)
+      // Double slash
+      .replace(/\/\//g, '/')
+  )
 }
 
 module.exports = {
   escapeFormat,
-  escapeFormatSlashes
-};
+  escapeFormatSlashes,
+}
diff --git a/lib/php-version.js b/lib/php-version.js
index 2e3b9a4193ecbd271ed630dc2cc0530197db27b9..eaaf1f28ab1a2727918862ba8e7695d06f50d63f 100644
--- a/lib/php-version.js
+++ b/lib/php-version.js
@@ -3,23 +3,23 @@
  * using the algorithm followed by Composer (see
  * https://getcomposer.org/doc/04-schema.md#version).
  */
-'use strict';
+'use strict'
 
-const request = require('request');
-const uniq = require('lodash.uniq');
-const {listCompare} = require('./version');
-const {omitv} = require('./text-formatters');
-const { regularUpdate } = require('./regular-update');
+const request = require('request')
+const uniq = require('lodash.uniq')
+const { listCompare } = require('./version')
+const { omitv } = require('./text-formatters')
+const { regularUpdate } = require('./regular-update')
 
 // Return a negative value if v1 < v2,
 // zero if v1 = v2, a positive value otherwise.
 function asciiVersionCompare(v1, v2) {
   if (v1 < v2) {
-    return -1;
+    return -1
   } else if (v1 > v2) {
-    return 1;
+    return 1
   } else {
-    return 0;
+    return 0
   }
 }
 
@@ -29,8 +29,8 @@ function asciiVersionCompare(v1, v2) {
 function numberedVersionData(version) {
   // A version has a numbered part and a modifier part
   // (eg, 1.0.0-patch, 2.0.x-dev).
-  const parts = version.split('-');
-  const numbered = parts[0];
+  const parts = version.split('-')
+  const numbered = parts[0]
 
   // Aliases that get caught here.
   if (numbered === 'dev') {
@@ -38,74 +38,79 @@ function numberedVersionData(version) {
       numbers: parts[1],
       modifier: 5,
       modifierCount: 1,
-    };
+    }
   }
 
-  let modifierLevel = 3;
-  let modifierLevelCount = 0;
+  let modifierLevel = 3
+  let modifierLevelCount = 0
 
   if (parts.length > 1) {
-    const modifier = parts[parts.length - 1];
-    const firstLetter = modifier.charCodeAt(0);
-    let modifierLevelCountString;
+    const modifier = parts[parts.length - 1]
+    const firstLetter = modifier.charCodeAt(0)
+    let modifierLevelCountString
 
     // Modifiers: alpha < beta < RC < normal < patch < dev
-    if (firstLetter === 97) { // a
-      modifierLevel = 0;
+    if (firstLetter === 97) {
+      // a
+      modifierLevel = 0
       if (/^alpha/.test(modifier)) {
-        modifierLevelCountString = + (modifier.slice(5));
+        modifierLevelCountString = +modifier.slice(5)
       } else {
-        modifierLevelCountString = + (modifier.slice(1));
+        modifierLevelCountString = +modifier.slice(1)
       }
-    } else if (firstLetter === 98) { // b
-      modifierLevel = 1;
+    } else if (firstLetter === 98) {
+      // b
+      modifierLevel = 1
       if (/^beta/.test(modifier)) {
-        modifierLevelCountString = + (modifier.slice(4));
+        modifierLevelCountString = +modifier.slice(4)
       } else {
-        modifierLevelCountString = + (modifier.slice(1));
+        modifierLevelCountString = +modifier.slice(1)
       }
-    } else if (firstLetter === 82) { // R
-      modifierLevel = 2;
-      modifierLevelCountString = + (modifier.slice(2));
-    } else if (firstLetter === 112) { // p
-      modifierLevel = 4;
+    } else if (firstLetter === 82) {
+      // R
+      modifierLevel = 2
+      modifierLevelCountString = +modifier.slice(2)
+    } else if (firstLetter === 112) {
+      // p
+      modifierLevel = 4
       if (/^patch/.test(modifier)) {
-        modifierLevelCountString = + (modifier.slice(5));
+        modifierLevelCountString = +modifier.slice(5)
       } else {
-        modifierLevelCountString = + (modifier.slice(1));
+        modifierLevelCountString = +modifier.slice(1)
       }
-    } else if (firstLetter === 100) { // d
-      modifierLevel = 5;
+    } else if (firstLetter === 100) {
+      // d
+      modifierLevel = 5
       if (/^dev/.test(modifier)) {
-        modifierLevelCountString = + (modifier.slice(3));
+        modifierLevelCountString = +modifier.slice(3)
       } else {
-        modifierLevelCountString = + (modifier.slice(1));
+        modifierLevelCountString = +modifier.slice(1)
       }
     }
 
     // If we got the empty string, it defaults to a modifier count of 1.
     if (!modifierLevelCountString) {
-      modifierLevelCount = 1;
+      modifierLevelCount = 1
     } else {
-      modifierLevelCount = + modifierLevelCountString;
+      modifierLevelCount = +modifierLevelCountString
     }
   }
 
   // Try to convert to a list of numbers.
-  function toNum (s) {
-    let n = +s;
+  function toNum(s) {
+    let n = +s
     if (Number.isNaN(n)) {
-      n = 0xffffffff;
+      n = 0xffffffff
     }
-    return n;
+    return n
   }
-  const numberList = numbered.split('.').map(toNum);
+  const numberList = numbered.split('.').map(toNum)
 
   return {
     numbers: numberList,
     modifier: modifierLevel,
     modifierCount: modifierLevelCount,
-  };
+  }
 }
 
 // Return a negative value if v1 < v2,
@@ -116,111 +121,121 @@ function numberedVersionData(version) {
 // and https://github.com/badges/shields/issues/319#issuecomment-74411045
 function compare(v1, v2) {
   // Omit the starting `v`.
-  const rawv1 = omitv(v1);
-  const rawv2 = omitv(v2);
-  let v1data, v2data;
+  const rawv1 = omitv(v1)
+  const rawv2 = omitv(v2)
+  let v1data, v2data
   try {
-    v1data = numberedVersionData(rawv1);
-    v2data = numberedVersionData(rawv2);
-  } catch(e) {
-    return asciiVersionCompare(rawv1, rawv2);
+    v1data = numberedVersionData(rawv1)
+    v2data = numberedVersionData(rawv2)
+  } catch (e) {
+    return asciiVersionCompare(rawv1, rawv2)
   }
 
   // Compare the numbered part (eg, 1.0.0 < 2.0.0).
-  const numbersCompare = listCompare(v1data.numbers, v2data.numbers);
+  const numbersCompare = listCompare(v1data.numbers, v2data.numbers)
   if (numbersCompare !== 0) {
-    return numbersCompare;
+    return numbersCompare
   }
 
   // Compare the modifiers (eg, alpha < beta).
   if (v1data.modifier < v2data.modifier) {
-    return -1;
+    return -1
   } else if (v1data.modifier > v2data.modifier) {
-    return 1;
+    return 1
   }
 
   // Compare the modifier counts (eg, alpha1 < alpha3).
   if (v1data.modifierCount < v2data.modifierCount) {
-    return -1;
+    return -1
   } else if (v1data.modifierCount > v2data.modifierCount) {
-    return 1;
+    return 1
   }
 
-  return 0;
+  return 0
 }
 
 function latest(versions) {
-  let latest = versions[0];
+  let latest = versions[0]
   for (let i = 1; i < versions.length; i++) {
     if (compare(latest, versions[i]) < 0) {
-      latest = versions[i];
+      latest = versions[i]
     }
   }
-  return latest;
+  return latest
 }
 
 function isStable(version) {
-  const rawVersion = omitv(version);
-  let versionData;
+  const rawVersion = omitv(version)
+  let versionData
   try {
-    versionData = numberedVersionData(rawVersion);
-  } catch(e) {
-    return false;
+    versionData = numberedVersionData(rawVersion)
+  } catch (e) {
+    return false
   }
   // normal or patch
-  return (versionData.modifier === 3) || (versionData.modifier === 4);
+  return versionData.modifier === 3 || versionData.modifier === 4
 }
 
 function minorVersion(version) {
-  const result = version.match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
+  const result = version.match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?/)
 
   if (result === null) {
-    return '';
+    return ''
   }
 
-  return result[1] + '.' + (result[2] ? result[2] : '0');
+  return result[1] + '.' + (result[2] ? result[2] : '0')
 }
 
 function versionReduction(versions, phpReleases) {
   if (!versions.length) {
-    return '';
+    return ''
   }
 
   // versions intersect
-  versions = uniq(versions).sort().filter((n) => phpReleases.includes(n));
+  versions = uniq(versions)
+    .sort()
+    .filter(n => phpReleases.includes(n))
 
   // nothing to reduction
   if (versions.length < 2) {
-    return versions.length ? versions[0] : '';
+    return versions.length ? versions[0] : ''
   }
 
-  const first = phpReleases.indexOf(versions[0]);
-  const last = phpReleases.indexOf(versions[versions.length - 1]);
+  const first = phpReleases.indexOf(versions[0])
+  const last = phpReleases.indexOf(versions[versions.length - 1])
 
   // no missed versions
   if (first + versions.length - 1 === last) {
     if (last === phpReleases.length - 1) {
-      return '>= ' + (versions[0][2] === '0' ? versions[0][0] : versions[0]); // 7.0 -> 7
+      return '>= ' + (versions[0][2] === '0' ? versions[0][0] : versions[0]) // 7.0 -> 7
     }
 
-    return versions[0] + ' - ' + versions[versions.length - 1];
+    return versions[0] + ' - ' + versions[versions.length - 1]
   }
 
-  return versions.join(', ');
+  return versions.join(', ')
 }
 
 function getPhpReleases(githubApiProvider, cb) {
-  regularUpdate({
-    url: '/repos/php/php-src/git/refs/tags',
-    intervalMillis: 24 * 3600 * 1000, // 1 day
-    scraper: tags => uniq(
-      tags
-        // only releases
-        .filter(tag => tag.ref.match(/^refs\/tags\/php-\d+\.\d+\.\d+$/) != null)
-        // get minor version of release
-        .map(tag => tag.ref.match(/^refs\/tags\/php-(\d+\.\d+)\.\d+$/)[1])),
-    request: (url, options, cb) => githubApiProvider.request(request, url, {}, cb),
-  }, cb);
+  regularUpdate(
+    {
+      url: '/repos/php/php-src/git/refs/tags',
+      intervalMillis: 24 * 3600 * 1000, // 1 day
+      scraper: tags =>
+        uniq(
+          tags
+            // only releases
+            .filter(
+              tag => tag.ref.match(/^refs\/tags\/php-\d+\.\d+\.\d+$/) != null
+            )
+            // get minor version of release
+            .map(tag => tag.ref.match(/^refs\/tags\/php-(\d+\.\d+)\.\d+$/)[1])
+        ),
+      request: (url, options, cb) =>
+        githubApiProvider.request(request, url, {}, cb),
+    },
+    cb
+  )
 }
 
 module.exports = {
@@ -230,4 +245,4 @@ module.exports = {
   minorVersion,
   versionReduction,
   getPhpReleases,
-};
+}
diff --git a/lib/php-version.spec.js b/lib/php-version.spec.js
index 1d1606049e77f2157e0b1518a94f13a153bc31b6..c73e959593b45b40b55c9bea80f9c45ad626f4f2 100644
--- a/lib/php-version.spec.js
+++ b/lib/php-version.spec.js
@@ -1,64 +1,76 @@
-'use strict';
+'use strict'
 
-const { test, given } = require('sazerac');
-const {
-  compare,
-  minorVersion,
-  versionReduction
-} = require('./php-version');
+const { test, given } = require('sazerac')
+const { compare, minorVersion, versionReduction } = require('./php-version')
 
-const phpReleases = ['5.0', '5.1', '5.2', '5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2'];
+const phpReleases = [
+  '5.0',
+  '5.1',
+  '5.2',
+  '5.3',
+  '5.4',
+  '5.5',
+  '5.6',
+  '7.0',
+  '7.1',
+  '7.2',
+]
 
 describe('Text PHP version', function() {
   test(minorVersion, () => {
-      given('7').expect('7.0');
-      given('7.1').expect('7.1');
-      given('5.3.3').expect('5.3');
-      given('hhvm').expect('');
-  });
+    given('7').expect('7.0')
+    given('7.1').expect('7.1')
+    given('5.3.3').expect('5.3')
+    given('hhvm').expect('')
+  })
 
   test(versionReduction, () => {
-    given(['5.3', '5.4', '5.5'], phpReleases).expect('5.3 - 5.5');
-    given(['5.4', '5.5', '5.6', '7.0', '7.1'], phpReleases).expect('5.4 - 7.1');
-    given(['5.5', '5.6', '7.0', '7.1', '7.2'], phpReleases).expect('>= 5.5');
-    given(['5.5', '5.6', '7.1', '7.2'], phpReleases).expect('5.5, 5.6, 7.1, 7.2');
-    given(['7.0', '7.1', '7.2'], phpReleases).expect('>= 7');
-    given(['5.0', '5.1', '5.2', '5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2'], phpReleases).expect('>= 5');
-    given(['7.1', '7.2'], phpReleases).expect('>= 7.1');
-    given(['7.1'], phpReleases).expect('7.1');
-    given(['8.1'], phpReleases).expect('');
-    given([]).expect('');
-  });
-});
+    given(['5.3', '5.4', '5.5'], phpReleases).expect('5.3 - 5.5')
+    given(['5.4', '5.5', '5.6', '7.0', '7.1'], phpReleases).expect('5.4 - 7.1')
+    given(['5.5', '5.6', '7.0', '7.1', '7.2'], phpReleases).expect('>= 5.5')
+    given(['5.5', '5.6', '7.1', '7.2'], phpReleases).expect(
+      '5.5, 5.6, 7.1, 7.2'
+    )
+    given(['7.0', '7.1', '7.2'], phpReleases).expect('>= 7')
+    given(
+      ['5.0', '5.1', '5.2', '5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2'],
+      phpReleases
+    ).expect('>= 5')
+    given(['7.1', '7.2'], phpReleases).expect('>= 7.1')
+    given(['7.1'], phpReleases).expect('7.1')
+    given(['8.1'], phpReleases).expect('')
+    given([]).expect('')
+  })
+})
 
 describe('Composer version comparison', function() {
   test(compare, () => {
     // composer version scheme ordering
-    given('0.9.0', '1.0.0-alpha').expect(-1);
-    given('1.0.0-alpha', '1.0.0-alpha2').expect(-1);
-    given('1.0.0-alpha2', '1.0.0-beta').expect(-1);
-    given('1.0.0-beta', '1.0.0-beta2').expect(-1);
-    given('1.0.0-beta2', '1.0.0-RC').expect(-1);
-    given('1.0.0-RC', '1.0.0-RC2').expect(-1);
-    given('1.0.0-RC2', '1.0.0').expect(-1);
-    given('1.0.0', '1.0.0-patch').expect(-1);
-    given('1.0.0-patch', '1.0.0-dev').expect(-1);
-    given('1.0.0-dev', '1.0.1').expect(-1);
-    given('1.0.1', '1.0.x-dev').expect(-1);
+    given('0.9.0', '1.0.0-alpha').expect(-1)
+    given('1.0.0-alpha', '1.0.0-alpha2').expect(-1)
+    given('1.0.0-alpha2', '1.0.0-beta').expect(-1)
+    given('1.0.0-beta', '1.0.0-beta2').expect(-1)
+    given('1.0.0-beta2', '1.0.0-RC').expect(-1)
+    given('1.0.0-RC', '1.0.0-RC2').expect(-1)
+    given('1.0.0-RC2', '1.0.0').expect(-1)
+    given('1.0.0', '1.0.0-patch').expect(-1)
+    given('1.0.0-patch', '1.0.0-dev').expect(-1)
+    given('1.0.0-dev', '1.0.1').expect(-1)
+    given('1.0.1', '1.0.x-dev').expect(-1)
 
     // short versions should compare equal to long versions
-    given('1.0.0-p', '1.0.0-patch').expect(0);
-    given('1.0.0-a', '1.0.0-alpha').expect(0);
-    given('1.0.0-a2', '1.0.0-alpha2').expect(0);
-    given('1.0.0-b', '1.0.0-beta').expect(0);
-    given('1.0.0-b2', '1.0.0-beta2').expect(0);
+    given('1.0.0-p', '1.0.0-patch').expect(0)
+    given('1.0.0-a', '1.0.0-alpha').expect(0)
+    given('1.0.0-a2', '1.0.0-alpha2').expect(0)
+    given('1.0.0-b', '1.0.0-beta').expect(0)
+    given('1.0.0-b2', '1.0.0-beta2').expect(0)
 
     // numeric suffixes
-    given('1.0.0-b1', '1.0.0-b2').expect(-1);
-    given('1.0.0-b10', '1.0.0-b11').expect(-1);
-    given('1.0.0-a1', '1.0.0-a2').expect(-1);
-    given('1.0.0-a10', '1.0.0-a11').expect(-1);
-    given('1.0.0-RC1', '1.0.0-RC2').expect(-1);
-    given('1.0.0-RC10', '1.0.0-RC11').expect(-1);
-  });
-});
+    given('1.0.0-b1', '1.0.0-b2').expect(-1)
+    given('1.0.0-b10', '1.0.0-b11').expect(-1)
+    given('1.0.0-a1', '1.0.0-a2').expect(-1)
+    given('1.0.0-a10', '1.0.0-a11').expect(-1)
+    given('1.0.0-RC1', '1.0.0-RC2').expect(-1)
+    given('1.0.0-RC10', '1.0.0-RC11').expect(-1)
+  })
+})
diff --git a/lib/pypi-helpers.js b/lib/pypi-helpers.js
index beaeb5a488d86b0577b4d84e993e01c2b805499d..b51d018883315a58fb21bb56f9fb270687976348 100644
--- a/lib/pypi-helpers.js
+++ b/lib/pypi-helpers.js
@@ -1,4 +1,4 @@
-'use strict';
+'use strict'
 
 /*
   Django versions will be specified in the form major.minor
@@ -9,43 +9,49 @@
 */
 
 const parseDjangoVersionString = function(str) {
-  if (typeof(str) !== 'string') { return false; }
-  const x = str.split('.');
-  const maj = parseInt(x[0]) || 0;
-  const min = parseInt(x[1]) || 0;
+  if (typeof str !== 'string') {
+    return false
+  }
+  const x = str.split('.')
+  const maj = parseInt(x[0]) || 0
+  const min = parseInt(x[1]) || 0
   return {
-      major: maj,
-      minor: min
-  };
-};
+    major: maj,
+    minor: min,
+  }
+}
 
 // sort an array of django versions low to high
 const sortDjangoVersions = function(versions) {
   return versions.sort(function(a, b) {
-    if (parseDjangoVersionString(a).major === parseDjangoVersionString(b).major) {
-      return parseDjangoVersionString(a).minor - parseDjangoVersionString(b).minor;
+    if (
+      parseDjangoVersionString(a).major === parseDjangoVersionString(b).major
+    ) {
+      return (
+        parseDjangoVersionString(a).minor - parseDjangoVersionString(b).minor
+      )
     } else {
-      return parseDjangoVersionString(a).major - parseDjangoVersionString(b).major;
+      return (
+        parseDjangoVersionString(a).major - parseDjangoVersionString(b).major
+      )
     }
-  });
-};
-
+  })
+}
 
 // extract classifiers from a pypi json response based on a regex
 const parseClassifiers = function(parsedData, pattern) {
-  const results = [];
+  const results = []
   for (let i = 0; i < parsedData.info.classifiers.length; i++) {
-    const matched = pattern.exec(parsedData.info.classifiers[i]);
+    const matched = pattern.exec(parsedData.info.classifiers[i])
     if (matched && matched[1]) {
-      results.push(matched[1].toLowerCase());
+      results.push(matched[1].toLowerCase())
     }
   }
-  return results;
-};
-
+  return results
+}
 
 module.exports = {
   parseClassifiers,
   parseDjangoVersionString,
-  sortDjangoVersions
-};
+  sortDjangoVersions,
+}
diff --git a/lib/pypi-helpers.spec.js b/lib/pypi-helpers.spec.js
index 65041b13660409dceb61596b28296c449af3a19e..1d62eeff972d6dc185cd48fd957473903690ad25 100644
--- a/lib/pypi-helpers.spec.js
+++ b/lib/pypi-helpers.spec.js
@@ -1,78 +1,102 @@
-'use strict';
+'use strict'
 
-const { test, given } = require('sazerac');
+const { test, given } = require('sazerac')
 const {
   parseClassifiers,
   parseDjangoVersionString,
-  sortDjangoVersions
-} = require('./pypi-helpers.js');
+  sortDjangoVersions,
+} = require('./pypi-helpers.js')
 
 const classifiersFixture = {
   info: {
     classifiers: [
-      "Development Status :: 5 - Production/Stable",
-      "Environment :: Web Environment",
-      "Framework :: Django",
-      "Framework :: Django :: 1.10",
-      "Framework :: Django :: 1.11",
-      "Intended Audience :: Developers",
-      "Intended Audience :: Developers",
-      "License :: OSI Approved :: BSD License",
-      "Operating System :: OS Independent",
-      "Natural Language :: English",
-      "Programming Language :: Python",
-      "Programming Language :: Python :: 2",
-      "Programming Language :: Python :: 2.7",
-      "Programming Language :: Python :: 3",
-      "Programming Language :: Python :: 3.4",
-      "Programming Language :: Python :: 3.5",
-      "Programming Language :: Python :: 3.6",
-      "Topic :: Internet :: WWW/HTTP",
-      "Programming Language :: Python :: Implementation :: CPython",
-      "Programming Language :: Python :: Implementation :: PyPy"
-    ]
-  }
-};
+      'Development Status :: 5 - Production/Stable',
+      'Environment :: Web Environment',
+      'Framework :: Django',
+      'Framework :: Django :: 1.10',
+      'Framework :: Django :: 1.11',
+      'Intended Audience :: Developers',
+      'Intended Audience :: Developers',
+      'License :: OSI Approved :: BSD License',
+      'Operating System :: OS Independent',
+      'Natural Language :: English',
+      'Programming Language :: Python',
+      'Programming Language :: Python :: 2',
+      'Programming Language :: Python :: 2.7',
+      'Programming Language :: Python :: 3',
+      'Programming Language :: Python :: 3.4',
+      'Programming Language :: Python :: 3.5',
+      'Programming Language :: Python :: 3.6',
+      'Topic :: Internet :: WWW/HTTP',
+      'Programming Language :: Python :: Implementation :: CPython',
+      'Programming Language :: Python :: Implementation :: PyPy',
+    ],
+  },
+}
 
 describe('PyPI helpers', function() {
   test(parseClassifiers, function() {
-    given(classifiersFixture, /^Programming Language :: Python :: ([\d.]+)$/)
-      .expect(["2","2.7","3","3.4","3.5","3.6"]);
+    given(
+      classifiersFixture,
+      /^Programming Language :: Python :: ([\d.]+)$/
+    ).expect(['2', '2.7', '3', '3.4', '3.5', '3.6'])
 
-    given(classifiersFixture, /^Framework :: Django :: ([\d.]+)$/)
-      .expect(["1.10", "1.11"]);
+    given(classifiersFixture, /^Framework :: Django :: ([\d.]+)$/).expect([
+      '1.10',
+      '1.11',
+    ])
 
-    given(classifiersFixture, /^Programming Language :: Python :: Implementation :: (\S+)$/)
-      .expect(["cpython", "pypy"]);
+    given(
+      classifiersFixture,
+      /^Programming Language :: Python :: Implementation :: (\S+)$/
+    ).expect(['cpython', 'pypy'])
 
     // regex that matches everything
-    given(classifiersFixture, /^([\S\s+]+)$/)
-      .expect(classifiersFixture.info.classifiers.map(function(e) {
-        return e.toLowerCase();
-      }));
+    given(classifiersFixture, /^([\S\s+]+)$/).expect(
+      classifiersFixture.info.classifiers.map(function(e) {
+        return e.toLowerCase()
+      })
+    )
 
     // regex that matches nothing
-    given(classifiersFixture, /^(?!.*)*$/)
-      .expect([]);
-  });
+    given(classifiersFixture, /^(?!.*)*$/).expect([])
+  })
 
   test(parseDjangoVersionString, function() {
-    given("1").expect({ major: 1, minor: 0});
-    given("1.0").expect({ major: 1, minor: 0});
-    given("7.2").expect({ major: 7, minor: 2});
-    given("7.2derpderp").expect({ major: 7, minor: 2});
-    given("7.2.9.5.8.3").expect({ major: 7, minor: 2});
-    given("foo").expect({ major: 0, minor: 0});
-  });
+    given('1').expect({ major: 1, minor: 0 })
+    given('1.0').expect({ major: 1, minor: 0 })
+    given('7.2').expect({ major: 7, minor: 2 })
+    given('7.2derpderp').expect({ major: 7, minor: 2 })
+    given('7.2.9.5.8.3').expect({ major: 7, minor: 2 })
+    given('foo').expect({ major: 0, minor: 0 })
+  })
 
   test(sortDjangoVersions, function() {
-    given(["2.0", "1.9", "10", "1.11", "2.1", "2.11",])
-      .expect(["1.9", "1.11", "2.0", "2.1", "2.11", "10"]);
+    given(['2.0', '1.9', '10', '1.11', '2.1', '2.11']).expect([
+      '1.9',
+      '1.11',
+      '2.0',
+      '2.1',
+      '2.11',
+      '10',
+    ])
 
-    given(["2", "1.9", "10", "1.11", "2.1", "2.11",])
-      .expect(["1.9", "1.11", "2", "2.1", "2.11", "10"]);
+    given(['2', '1.9', '10', '1.11', '2.1', '2.11']).expect([
+      '1.9',
+      '1.11',
+      '2',
+      '2.1',
+      '2.11',
+      '10',
+    ])
 
-    given(["2.0rc1", "10", "1.9", "1.11", "2.1", "2.11",])
-      .expect(["1.9", "1.11", "2.0rc1", "2.1", "2.11", "10"]);
-  });
-});
+    given(['2.0rc1', '10', '1.9', '1.11', '2.1', '2.11']).expect([
+      '1.9',
+      '1.11',
+      '2.0rc1',
+      '2.1',
+      '2.11',
+      '10',
+    ])
+  })
+})
diff --git a/lib/register-chai-plugins.spec.js b/lib/register-chai-plugins.spec.js
index c10ec2cc17581a721cd60a6c150732306ff709a1..0873f4c86344f6fbbcb7edfe7e21efa05694ec9a 100644
--- a/lib/register-chai-plugins.spec.js
+++ b/lib/register-chai-plugins.spec.js
@@ -1,6 +1,6 @@
-'use strict';
+'use strict'
 
-const { use } = require('chai');
+const { use } = require('chai')
 
-use(require('chai-string'));
-use(require('sinon-chai'));
+use(require('chai-string'))
+use(require('sinon-chai'))
diff --git a/lib/regular-update.js b/lib/regular-update.js
index 3a79b0b965f74d8dc1c22909ff5ccc2db5f82a24..54651d1ec24c1b2c1453cd73124e7ad292e41af0 100644
--- a/lib/regular-update.js
+++ b/lib/regular-update.js
@@ -1,53 +1,64 @@
-'use strict';
+'use strict'
 
 // Map from URL to { timestamp: last fetch time, data: data }.
-let regularUpdateCache = Object.create(null);
+let regularUpdateCache = Object.create(null)
 
 // url: a string, scraper: a function that takes string data at that URL.
 // interval: number in milliseconds.
 // cb: a callback function that takes an error and data returned by the scraper.
-function regularUpdate({
-  url,
-  intervalMillis,
-  json = true,
-  scraper = buffer => buffer,
-  options = {},
-  request = require('request'),
-}, cb) {
-  const timestamp = Date.now();
-  const cached = regularUpdateCache[url];
-  if (cached != null &&
-      (timestamp - cached.timestamp) < intervalMillis) {
-    cb(null, cached.data);
-    return;
+function regularUpdate(
+  {
+    url,
+    intervalMillis,
+    json = true,
+    scraper = buffer => buffer,
+    options = {},
+    request = require('request'),
+  },
+  cb
+) {
+  const timestamp = Date.now()
+  const cached = regularUpdateCache[url]
+  if (cached != null && timestamp - cached.timestamp < intervalMillis) {
+    cb(null, cached.data)
+    return
   }
   request(url, options, (err, res, buffer) => {
-    if (err != null) { cb(err); return; }
+    if (err != null) {
+      cb(err)
+      return
+    }
 
-    let reqData;
+    let reqData
     if (json) {
       try {
-        reqData = JSON.parse(buffer);
-      } catch(e) { cb(e); return; }
+        reqData = JSON.parse(buffer)
+      } catch (e) {
+        cb(e)
+        return
+      }
     } else {
-      reqData = buffer;
+      reqData = buffer
     }
 
-    let data;
+    let data
     try {
-      data = scraper(reqData);
-    } catch(e) { cb(e); return; }
+      data = scraper(reqData)
+    } catch (e) {
+      cb(e)
+      return
+    }
 
-    regularUpdateCache[url] = { timestamp, data };
-    cb(null, data);
-  });
+    regularUpdateCache[url] = { timestamp, data }
+    cb(null, data)
+  })
 }
 
 function clearRegularUpdateCache() {
-  regularUpdateCache = Object.create(null);
+  regularUpdateCache = Object.create(null)
 }
 
 module.exports = {
   regularUpdate,
-  clearRegularUpdateCache
-};
+  clearRegularUpdateCache,
+}
diff --git a/lib/request-handler.js b/lib/request-handler.js
index 80f34396bc6abc9e5e546446e995e2d962bbc75b..bde110f2aedcdf038e335a2bc116f779e875d7c5 100644
--- a/lib/request-handler.js
+++ b/lib/request-handler.js
@@ -1,19 +1,19 @@
-'use strict';
+'use strict'
 
 // eslint-disable-next-line node/no-deprecated-api
-const domain = require('domain');
-const request = require('request');
-const { makeBadgeData: getBadgeData } = require('./badge-data');
-const log = require('./log');
-const LruCache = require('./lru-cache');
-const analytics = require('./analytics');
-const { makeSend } = require('./result-sender');
-const queryString = require('query-string');
-const { Inaccessible } = require('../services/errors');
+const domain = require('domain')
+const request = require('request')
+const { makeBadgeData: getBadgeData } = require('./badge-data')
+const log = require('./log')
+const LruCache = require('./lru-cache')
+const analytics = require('./analytics')
+const { makeSend } = require('./result-sender')
+const queryString = require('query-string')
+const { Inaccessible } = require('../services/errors')
 
 // We avoid calling the vendor's server for computation of the information in a
 // number of badges.
-const minAccuracy = 0.75;
+const minAccuracy = 0.75
 
 // The quotient of (vendor) data change frequency by badge request frequency
 // must be lower than this to trigger sending the cached data *before*
@@ -22,16 +22,16 @@ const minAccuracy = 0.75;
 // A(Δt) = 1 - min(# data change over Δt, # requests over Δt)
 //             / (# requests over Δt)
 //       = 1 - max(1, df) / rf
-const freqRatioMax = 1 - minAccuracy;
+const freqRatioMax = 1 - minAccuracy
 
 // Request cache size of 5MB (~5000 bytes/image).
-const requestCache = new LruCache(1000);
+const requestCache = new LruCache(1000)
 
 // Deep error handling for vendor hooks.
-const vendorDomain = domain.create();
+const vendorDomain = domain.create()
 vendorDomain.on('error', err => {
-  log.error('Vendor hook error:', err.stack);
-});
+  log.error('Vendor hook error:', err.stack)
+})
 
 // These query parameters are available to any badge. For the most part they
 // are used by makeBadgeData (see `lib/badge-data.js`) and related functions.
@@ -46,14 +46,14 @@ const globalQueryParams = new Set([
   'link',
   'colorA',
   'colorB',
-]);
+])
 
 function flattenQueryParams(queryParams) {
-  const union = new Set(globalQueryParams);
-  (queryParams || []).forEach(name => {
-    union.add(name);
-  });
-  return Array.from(union).sort();
+  const union = new Set(globalQueryParams)
+  ;(queryParams || []).forEach(name => {
+    union.add(name)
+  })
+  return Array.from(union).sort()
 }
 
 // handlerOptions can contain:
@@ -71,178 +71,201 @@ function flattenQueryParams(queryParams) {
 // Pass just the handler function as shorthand.
 //
 // Inject `makeBadge` as a dependency.
-function handleRequest (makeBadge, handlerOptions) {
+function handleRequest(makeBadge, handlerOptions) {
   if (typeof handlerOptions === 'function') {
     handlerOptions = { handler: handlerOptions }
   }
 
-  const allowedKeys = flattenQueryParams(handlerOptions.queryParams);
+  const allowedKeys = flattenQueryParams(handlerOptions.queryParams)
 
   return (queryParams, match, end, ask) => {
-    const reqTime = new Date();
+    const reqTime = new Date()
 
-    let maxAge = isInt(process.env.BADGE_MAX_AGE_SECONDS) ? parseInt(process.env.BADGE_MAX_AGE_SECONDS) : 120;
-    if (
-        isInt(queryParams.maxAge)
-      && parseInt(queryParams.maxAge) > maxAge
-    ) {
+    let maxAge = isInt(process.env.BADGE_MAX_AGE_SECONDS)
+      ? parseInt(process.env.BADGE_MAX_AGE_SECONDS)
+      : 120
+    if (isInt(queryParams.maxAge) && parseInt(queryParams.maxAge) > maxAge) {
       // only queryParams.maxAge to override the default
       // if it is greater than env.BADGE_MAX_AGE_SECONDS
-      maxAge = parseInt(queryParams.maxAge);
+      maxAge = parseInt(queryParams.maxAge)
     }
     // send both Cache-Control max-age and Expires
     // in case the client implements HTTP/1.0 but not HTTP/1.1
     if (maxAge === 0) {
-      ask.res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
-      ask.res.setHeader('Expires', reqTime.toGMTString());
+      ask.res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
+      ask.res.setHeader('Expires', reqTime.toGMTString())
     } else {
-      ask.res.setHeader('Cache-Control', 'max-age=' + maxAge);
-      ask.res.setHeader('Expires', new Date(+reqTime + maxAge * 1000).toGMTString());
+      ask.res.setHeader('Cache-Control', 'max-age=' + maxAge)
+      ask.res.setHeader(
+        'Expires',
+        new Date(+reqTime + maxAge * 1000).toGMTString()
+      )
     }
 
-    ask.res.setHeader('Date', reqTime.toGMTString());
+    ask.res.setHeader('Date', reqTime.toGMTString())
 
-    analytics.noteRequest(queryParams, match);
+    analytics.noteRequest(queryParams, match)
 
-    const filteredQueryParams = {};
+    const filteredQueryParams = {}
     allowedKeys.forEach(key => {
-      filteredQueryParams[key] = queryParams[key];
-    });
+      filteredQueryParams[key] = queryParams[key]
+    })
 
     // Use sindresorhus query-string because it sorts the keys, whereas the
     // builtin querystring module relies on the iteration order.
-    const stringified = queryString.stringify(filteredQueryParams);
-    const cacheIndex = `${match[0]}?${stringified}`;
+    const stringified = queryString.stringify(filteredQueryParams)
+    const cacheIndex = `${match[0]}?${stringified}`
 
     // Should we return the data right away?
-    const cached = requestCache.get(cacheIndex);
-    let cachedVersionSent = false;
+    const cached = requestCache.get(cacheIndex)
+    let cachedVersionSent = false
     if (cached !== undefined) {
       // A request was made not long ago.
-      const tooSoon = (+reqTime - cached.time) < cached.interval;
-      if (tooSoon || (cached.dataChange / cached.reqs <= freqRatioMax)) {
-        const svg = makeBadge(cached.data.badgeData);
-        makeSend(cached.data.format, ask.res, end)(svg);
-        cachedVersionSent = true;
+      const tooSoon = +reqTime - cached.time < cached.interval
+      if (tooSoon || cached.dataChange / cached.reqs <= freqRatioMax) {
+        const svg = makeBadge(cached.data.badgeData)
+        makeSend(cached.data.format, ask.res, end)(svg)
+        cachedVersionSent = true
         // We do not wish to call the vendor servers.
-        if (tooSoon) { return; }
+        if (tooSoon) {
+          return
+        }
       }
     }
 
     // In case our vendor servers are unresponsive.
-    let serverUnresponsive = false;
+    let serverUnresponsive = false
     const serverResponsive = setTimeout(() => {
-      serverUnresponsive = true;
-      if (cachedVersionSent) { return; }
+      serverUnresponsive = true
+      if (cachedVersionSent) {
+        return
+      }
       if (requestCache.has(cacheIndex)) {
-        const cached = requestCache.get(cacheIndex).data;
-        const svg = makeBadge(cached.badgeData);
-        makeSend(cached.format, ask.res, end)(svg);
-        return;
+        const cached = requestCache.get(cacheIndex).data
+        const svg = makeBadge(cached.badgeData)
+        makeSend(cached.format, ask.res, end)(svg)
+        return
       }
-      ask.res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
-      const badgeData = getBadgeData('vendor', filteredQueryParams);
-      badgeData.text[1] = 'unresponsive';
-      let extension;
+      ask.res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
+      const badgeData = getBadgeData('vendor', filteredQueryParams)
+      badgeData.text[1] = 'unresponsive'
+      let extension
       try {
-        extension = match[0].split('.').pop();
-      } catch(e) { extension = 'svg'; }
+        extension = match[0].split('.').pop()
+      } catch (e) {
+        extension = 'svg'
+      }
       const svg = makeBadge(badgeData)
-      makeSend(extension, ask.res, end)(svg);
-    }, 25000);
+      makeSend(extension, ask.res, end)(svg)
+    }, 25000)
 
     // Only call vendor servers when last request is older than…
-    let cacheInterval = 5000;  // milliseconds
-    function cachingRequest (uri, options, callback) {
-      if ((typeof options === 'function') && !callback) { callback = options; }
+    let cacheInterval = 5000 // milliseconds
+    function cachingRequest(uri, options, callback) {
+      if (typeof options === 'function' && !callback) {
+        callback = options
+      }
       if (options && typeof options === 'object') {
-        options.uri = uri;
+        options.uri = uri
       } else if (typeof uri === 'string') {
-        options = {uri: uri};
+        options = { uri: uri }
       } else {
-        options = uri;
+        options = uri
       }
-      options.headers = options.headers || {};
-      options.headers['User-Agent'] = options.headers['User-Agent'] || 'Shields.io';
+      options.headers = options.headers || {}
+      options.headers['User-Agent'] =
+        options.headers['User-Agent'] || 'Shields.io'
 
       request(options, (err, res, body) => {
         if (res != null && res.headers != null) {
-          const cacheControl = res.headers['cache-control'];
+          const cacheControl = res.headers['cache-control']
           if (cacheControl != null) {
-            const age = cacheControl.match(/max-age=([0-9]+)/);
+            const age = cacheControl.match(/max-age=([0-9]+)/)
             // Would like to get some more test coverage on this before changing it.
             // eslint-disable-next-line no-self-compare
-            if (age != null && (+age[1] === +age[1])) {
-              cacheInterval = +age[1] * 1000;
+            if (age != null && +age[1] === +age[1]) {
+              cacheInterval = +age[1] * 1000
             }
           }
         }
-        callback(err, res, body);
-      });
+        callback(err, res, body)
+      })
     }
 
     // Wrapper around `cachingRequest` that returns a promise rather than
     // needing to pass a callback.
-    cachingRequest.asPromise = (uri, options) => new Promise((resolve, reject) => {
-      cachingRequest(uri, options, (err, res, buffer) => {
-        if (err) {
-          // Wrap the error in an Inaccessible so it can be identified
-          // by the BaseService handler.
-          reject(new Inaccessible({ underlyingError: err }));
-        } else {
-          resolve({ res, buffer });
-        }
-     });
-   });
+    cachingRequest.asPromise = (uri, options) =>
+      new Promise((resolve, reject) => {
+        cachingRequest(uri, options, (err, res, buffer) => {
+          if (err) {
+            // Wrap the error in an Inaccessible so it can be identified
+            // by the BaseService handler.
+            reject(new Inaccessible({ underlyingError: err }))
+          } else {
+            resolve({ res, buffer })
+          }
+        })
+      })
 
     vendorDomain.run(() => {
-      const result = handlerOptions.handler(filteredQueryParams, match, function sendBadge(format, badgeData) {
-        if (serverUnresponsive) { return; }
-        clearTimeout(serverResponsive);
-        // Check for a change in the data.
-        let dataHasChanged = false;
-        if (cached !== undefined
-          && cached.data.badgeData.text[1] !== badgeData.text[1]) {
-          dataHasChanged = true;
-        }
-        // Add format to badge data.
-        badgeData.format = format;
-        // Update information in the cache.
-        const updatedCache = {
-          reqs: cached? (cached.reqs + 1): 1,
-          dataChange: cached? (cached.dataChange + (dataHasChanged? 1: 0))
-                            : 1,
-          time: +reqTime,
-          interval: cacheInterval,
-          data: { format: format, badgeData: badgeData }
-        };
-        requestCache.set(cacheIndex, updatedCache);
-        if (!cachedVersionSent) {
-          const svg = makeBadge(badgeData);
-          makeSend(format, ask.res, end)(svg);
-        }
-      }, cachingRequest);
+      const result = handlerOptions.handler(
+        filteredQueryParams,
+        match,
+        function sendBadge(format, badgeData) {
+          if (serverUnresponsive) {
+            return
+          }
+          clearTimeout(serverResponsive)
+          // Check for a change in the data.
+          let dataHasChanged = false
+          if (
+            cached !== undefined &&
+            cached.data.badgeData.text[1] !== badgeData.text[1]
+          ) {
+            dataHasChanged = true
+          }
+          // Add format to badge data.
+          badgeData.format = format
+          // Update information in the cache.
+          const updatedCache = {
+            reqs: cached ? cached.reqs + 1 : 1,
+            dataChange: cached
+              ? cached.dataChange + (dataHasChanged ? 1 : 0)
+              : 1,
+            time: +reqTime,
+            interval: cacheInterval,
+            data: { format: format, badgeData: badgeData },
+          }
+          requestCache.set(cacheIndex, updatedCache)
+          if (!cachedVersionSent) {
+            const svg = makeBadge(badgeData)
+            makeSend(format, ask.res, end)(svg)
+          }
+        },
+        cachingRequest
+      )
       if (result && result.catch) {
         result.catch(err => {
-          throw err;
-        });
+          throw err
+        })
       }
-    });
-  };
+    })
+  }
 }
 
 function clearRequestCache() {
-  requestCache.clear();
+  requestCache.clear()
 }
 
 function isInt(number) {
-  return number !== undefined && /^[0-9]+$/.test(number);
+  return number !== undefined && /^[0-9]+$/.test(number)
 }
 
 module.exports = {
   handleRequest,
-  makeHandleRequestFn: makeBadge => handlerOptions => handleRequest(makeBadge, handlerOptions),
+  makeHandleRequestFn: makeBadge => handlerOptions =>
+    handleRequest(makeBadge, handlerOptions),
   clearRequestCache,
   // Expose for testing.
-  _requestCache: requestCache
-};
+  _requestCache: requestCache,
+}
diff --git a/lib/request-handler.spec.js b/lib/request-handler.spec.js
index 1582ed56391709d0473d494d4982491e42459867..d3fc1b4f12b8b7e272f889b701fb450e859f1598 100644
--- a/lib/request-handler.spec.js
+++ b/lib/request-handler.spec.js
@@ -1,188 +1,209 @@
-'use strict';
-
-const { expect } = require('chai');
-const fetch = require('node-fetch');
-const config = require('./test-config');
-const Camp = require('camp');
-const analytics = require('./analytics');
-const { makeBadgeData: getBadgeData } = require('./badge-data');
+'use strict'
+
+const { expect } = require('chai')
+const fetch = require('node-fetch')
+const config = require('./test-config')
+const Camp = require('camp')
+const analytics = require('./analytics')
+const { makeBadgeData: getBadgeData } = require('./badge-data')
 const {
   makeHandleRequestFn,
   clearRequestCache,
-  _requestCache
-} = require('./request-handler');
-const testHelpers = require('./make-badge-test-helpers');
+  _requestCache,
+} = require('./request-handler')
+const testHelpers = require('./make-badge-test-helpers')
 
-const handleRequest = makeHandleRequestFn(testHelpers.makeBadge());
+const handleRequest = makeHandleRequestFn(testHelpers.makeBadge())
 
-const baseUri = `http://127.0.0.1:${config.port}`;
+const baseUri = `http://127.0.0.1:${config.port}`
 
-async function performTwoRequests (first, second) {
-  expect((await fetch(`${baseUri}${first}`)).ok).to.be.true;
-  expect((await fetch(`${baseUri}${second}`)).ok).to.be.true;
+async function performTwoRequests(first, second) {
+  expect((await fetch(`${baseUri}${first}`)).ok).to.be.true
+  expect((await fetch(`${baseUri}${second}`)).ok).to.be.true
 }
 
 function fakeHandler(queryParams, match, sendBadge, request) {
-  const [, someValue, format] = match;
-  const badgeData = getBadgeData('testing', queryParams);
-  badgeData.text[1] = someValue;
-  sendBadge(format, badgeData);
+  const [, someValue, format] = match
+  const badgeData = getBadgeData('testing', queryParams)
+  badgeData.text[1] = someValue
+  sendBadge(format, badgeData)
 }
 
 describe('The request handler', function() {
-  before(analytics.load);
+  before(analytics.load)
 
-  let camp;
-  const initialBadgeMaxAge = process.env.BADGE_MAX_AGE_SECONDS;
+  let camp
+  const initialBadgeMaxAge = process.env.BADGE_MAX_AGE_SECONDS
 
-  beforeEach(function (done) {
-    camp = Camp.start({ port: config.port, hostname: '::' });
-    camp.on('listening', () => done());
-  });
-  afterEach(function (done) {
-    clearRequestCache();
+  beforeEach(function(done) {
+    camp = Camp.start({ port: config.port, hostname: '::' })
+    camp.on('listening', () => done())
+  })
+  afterEach(function(done) {
+    clearRequestCache()
     if (camp) {
-      camp.close(() => done());
-      camp = null;
+      camp.close(() => done())
+      camp = null
     }
-    process.env.BADGE_MAX_AGE_SECONDS = initialBadgeMaxAge;
-  });
+    process.env.BADGE_MAX_AGE_SECONDS = initialBadgeMaxAge
+  })
 
   describe('the options object calling style', function() {
-    beforeEach(function () {
-      camp.route(/^\/testing\/([^/]+)\.(svg|png|gif|jpg|json)$/,
-        handleRequest({ handler: fakeHandler }));
-    });
-
-    it('should return the expected response', async function () {
-      const res = await fetch(`${baseUri}/testing/123.json`);
-      expect(res.ok).to.be.true;
-      expect(await res.json()).to.deep.equal({ name: 'testing', value: '123' });
-    });
-  });
+    beforeEach(function() {
+      camp.route(
+        /^\/testing\/([^/]+)\.(svg|png|gif|jpg|json)$/,
+        handleRequest({ handler: fakeHandler })
+      )
+    })
+
+    it('should return the expected response', async function() {
+      const res = await fetch(`${baseUri}/testing/123.json`)
+      expect(res.ok).to.be.true
+      expect(await res.json()).to.deep.equal({ name: 'testing', value: '123' })
+    })
+  })
 
   describe('the function shorthand calling style', function() {
-    beforeEach(function () {
-      camp.route(/^\/testing\/([^/]+)\.(svg|png|gif|jpg|json)$/,
-        handleRequest(fakeHandler));
-    });
-
-    it('should return the expected response', async function () {
-      const res = await fetch(`${baseUri}/testing/123.json`);
-      expect(res.ok).to.be.true;
-      expect(await res.json()).to.deep.equal({ name: 'testing', value: '123' });
-    });
-  });
-
-  describe('caching', function () {
-
-    describe('standard query parameters', function () {
-      let handlerCallCount;
-      beforeEach(function () {
-        handlerCallCount = 0;
-        camp.route(/^\/testing\/([^/]+)\.(svg|png|gif|jpg|json)$/,
+    beforeEach(function() {
+      camp.route(
+        /^\/testing\/([^/]+)\.(svg|png|gif|jpg|json)$/,
+        handleRequest(fakeHandler)
+      )
+    })
+
+    it('should return the expected response', async function() {
+      const res = await fetch(`${baseUri}/testing/123.json`)
+      expect(res.ok).to.be.true
+      expect(await res.json()).to.deep.equal({ name: 'testing', value: '123' })
+    })
+  })
+
+  describe('caching', function() {
+    describe('standard query parameters', function() {
+      let handlerCallCount
+      beforeEach(function() {
+        handlerCallCount = 0
+        camp.route(
+          /^\/testing\/([^/]+)\.(svg|png|gif|jpg|json)$/,
           handleRequest((queryParams, match, sendBadge, request) => {
-            ++handlerCallCount;
-            fakeHandler(queryParams, match, sendBadge, request);
-          }));
-      });
-
-      it('should cache identical requests', async function () {
-        await performTwoRequests('/testing/123.svg', '/testing/123.svg');
-        expect(handlerCallCount).to.equal(1);
-      });
-
-      it('should differentiate known query parameters', async function () {
+            ++handlerCallCount
+            fakeHandler(queryParams, match, sendBadge, request)
+          })
+        )
+      })
+
+      it('should cache identical requests', async function() {
+        await performTwoRequests('/testing/123.svg', '/testing/123.svg')
+        expect(handlerCallCount).to.equal(1)
+      })
+
+      it('should differentiate known query parameters', async function() {
         await performTwoRequests(
           '/testing/123.svg?label=foo',
           '/testing/123.svg?label=bar'
-        );
-        expect(handlerCallCount).to.equal(2);
-      });
+        )
+        expect(handlerCallCount).to.equal(2)
+      })
 
-      it('should ignore unknown query parameters', async function () {
+      it('should ignore unknown query parameters', async function() {
         await performTwoRequests(
           '/testing/123.svg?foo=1',
           '/testing/123.svg?foo=2'
-        );
-        expect(handlerCallCount).to.equal(1);
-      });
-
-      it('should set the expires header to current time + BADGE_MAX_AGE_SECONDS', async function () {
-        process.env.BADGE_MAX_AGE_SECONDS = 900;
-        const res = await fetch(`${baseUri}/testing/123.json`);
-        const expectedExpiry = new Date(+(new Date(res.headers.get('date'))) + 900000).toGMTString();
-        expect(res.headers.get('expires')).to.equal(expectedExpiry);
-        expect(res.headers.get('cache-control')).to.equal('max-age=900');
-      });
-
-      it('should set the expires header to current time + maxAge', async function () {
-        process.env.BADGE_MAX_AGE_SECONDS = 0;
-        const res = await fetch(`${baseUri}/testing/123.json?maxAge=3600`);
-        const expectedExpiry = new Date(+(new Date(res.headers.get('date'))) + 3600000).toGMTString();
-        expect(res.headers.get('expires')).to.equal(expectedExpiry);
-        expect(res.headers.get('cache-control')).to.equal('max-age=3600');
-      });
-
-      it('should ignore maxAge if maxAge < BADGE_MAX_AGE_SECONDS', async function () {
-        process.env.BADGE_MAX_AGE_SECONDS = 600;
-        const res = await fetch(`${baseUri}/testing/123.json?maxAge=300`);
-        const expectedExpiry = new Date(+(new Date(res.headers.get('date'))) + 600000).toGMTString();
-        expect(res.headers.get('expires')).to.equal(expectedExpiry);
-        expect(res.headers.get('cache-control')).to.equal('max-age=600');
-      });
-
-      it('should set Cache-Control: no-cache, no-store, must-revalidate if maxAge=0', async function () {
-        process.env.BADGE_MAX_AGE_SECONDS = 0;
-        const res = await fetch(`${baseUri}/testing/123.json`);
-        expect(res.headers.get('expires')).to.equal(res.headers.get('date'));
-        expect(res.headers.get('cache-control')).to.equal('no-cache, no-store, must-revalidate');
-      });
-
-      it('should set the expires header to current time + 120 if BADGE_MAX_AGE_SECONDS not set', async function () {
-        delete process.env.BADGE_MAX_AGE_SECONDS;
-        const res = await fetch(`${baseUri}/testing/123.json`);
-        const expectedExpiry = new Date(+(new Date(res.headers.get('date'))) + 120000).toGMTString();
-        expect(res.headers.get('expires')).to.equal(expectedExpiry);
-        expect(res.headers.get('cache-control')).to.equal('max-age=120');
-      });
-
-      describe('the cache key', function () {
-        const expectedCacheKey = '/testing/123.json?colorB=123&label=foo';
-        it('should match expected and use canonical order - 1', async function () {
-          const res = await fetch(`${baseUri}/testing/123.json?colorB=123&label=foo`);
-          expect(res.ok).to.be.true;
-          expect(_requestCache.cache).to.have.keys(expectedCacheKey);
-        });
-        it('should match expected and use canonical order - 2', async function () {
-          const res = await fetch(`${baseUri}/testing/123.json?label=foo&colorB=123`);
-          expect(res.ok).to.be.true;
-          expect(_requestCache.cache).to.have.keys(expectedCacheKey);
-        });
-      });
-    });
+        )
+        expect(handlerCallCount).to.equal(1)
+      })
+
+      it('should set the expires header to current time + BADGE_MAX_AGE_SECONDS', async function() {
+        process.env.BADGE_MAX_AGE_SECONDS = 900
+        const res = await fetch(`${baseUri}/testing/123.json`)
+        const expectedExpiry = new Date(
+          +new Date(res.headers.get('date')) + 900000
+        ).toGMTString()
+        expect(res.headers.get('expires')).to.equal(expectedExpiry)
+        expect(res.headers.get('cache-control')).to.equal('max-age=900')
+      })
+
+      it('should set the expires header to current time + maxAge', async function() {
+        process.env.BADGE_MAX_AGE_SECONDS = 0
+        const res = await fetch(`${baseUri}/testing/123.json?maxAge=3600`)
+        const expectedExpiry = new Date(
+          +new Date(res.headers.get('date')) + 3600000
+        ).toGMTString()
+        expect(res.headers.get('expires')).to.equal(expectedExpiry)
+        expect(res.headers.get('cache-control')).to.equal('max-age=3600')
+      })
+
+      it('should ignore maxAge if maxAge < BADGE_MAX_AGE_SECONDS', async function() {
+        process.env.BADGE_MAX_AGE_SECONDS = 600
+        const res = await fetch(`${baseUri}/testing/123.json?maxAge=300`)
+        const expectedExpiry = new Date(
+          +new Date(res.headers.get('date')) + 600000
+        ).toGMTString()
+        expect(res.headers.get('expires')).to.equal(expectedExpiry)
+        expect(res.headers.get('cache-control')).to.equal('max-age=600')
+      })
+
+      it('should set Cache-Control: no-cache, no-store, must-revalidate if maxAge=0', async function() {
+        process.env.BADGE_MAX_AGE_SECONDS = 0
+        const res = await fetch(`${baseUri}/testing/123.json`)
+        expect(res.headers.get('expires')).to.equal(res.headers.get('date'))
+        expect(res.headers.get('cache-control')).to.equal(
+          'no-cache, no-store, must-revalidate'
+        )
+      })
+
+      it('should set the expires header to current time + 120 if BADGE_MAX_AGE_SECONDS not set', async function() {
+        delete process.env.BADGE_MAX_AGE_SECONDS
+        const res = await fetch(`${baseUri}/testing/123.json`)
+        const expectedExpiry = new Date(
+          +new Date(res.headers.get('date')) + 120000
+        ).toGMTString()
+        expect(res.headers.get('expires')).to.equal(expectedExpiry)
+        expect(res.headers.get('cache-control')).to.equal('max-age=120')
+      })
+
+      describe('the cache key', function() {
+        const expectedCacheKey = '/testing/123.json?colorB=123&label=foo'
+        it('should match expected and use canonical order - 1', async function() {
+          const res = await fetch(
+            `${baseUri}/testing/123.json?colorB=123&label=foo`
+          )
+          expect(res.ok).to.be.true
+          expect(_requestCache.cache).to.have.keys(expectedCacheKey)
+        })
+        it('should match expected and use canonical order - 2', async function() {
+          const res = await fetch(
+            `${baseUri}/testing/123.json?label=foo&colorB=123`
+          )
+          expect(res.ok).to.be.true
+          expect(_requestCache.cache).to.have.keys(expectedCacheKey)
+        })
+      })
+    })
 
     describe('custom query parameters', function() {
-      let handlerCallCount;
-      beforeEach(function () {
-        handlerCallCount = 0;
-        camp.route(/^\/testing\/([^/]+)\.(svg|png|gif|jpg|json)$/,
+      let handlerCallCount
+      beforeEach(function() {
+        handlerCallCount = 0
+        camp.route(
+          /^\/testing\/([^/]+)\.(svg|png|gif|jpg|json)$/,
           handleRequest({
             queryParams: ['foo'],
             handler: (queryParams, match, sendBadge, request) => {
-              ++handlerCallCount;
-              fakeHandler(queryParams, match, sendBadge, request);
+              ++handlerCallCount
+              fakeHandler(queryParams, match, sendBadge, request)
             },
-          }))
-      });
+          })
+        )
+      })
 
-      it('should differentiate them', async function () {
+      it('should differentiate them', async function() {
         await performTwoRequests(
           '/testing/123.svg?foo=1',
           '/testing/123.svg?foo=2'
-        );
-        expect(handlerCallCount).to.equal(2);
-      });
-    });
-  });
-});
+        )
+        expect(handlerCallCount).to.equal(2)
+      })
+    })
+  })
+})
diff --git a/lib/result-sender.js b/lib/result-sender.js
index 6ea6ab697f3bccbaa9e8100b6e9c01cade78bff4..3aeed28907e8737b2a00cdcff0197ed95b7f27b0 100644
--- a/lib/result-sender.js
+++ b/lib/result-sender.js
@@ -1,49 +1,52 @@
-'use strict';
+'use strict'
 
-const stream = require('stream');
-const log = require('./log');
-const svg2img = require('./svg-to-img');
+const stream = require('stream')
+const log = require('./log')
+const svg2img = require('./svg-to-img')
 
 function streamFromString(str) {
-  const newStream = new stream.Readable();
-  newStream._read = () => { newStream.push(str); newStream.push(null); };
-  return newStream;
+  const newStream = new stream.Readable()
+  newStream._read = () => {
+    newStream.push(str)
+    newStream.push(null)
+  }
+  return newStream
 }
 
 function makeSend(format, askres, end) {
   if (format === 'svg') {
-    return res => sendSVG(res, askres, end);
+    return res => sendSVG(res, askres, end)
   } else if (format === 'json') {
-    return res => sendJSON(res, askres, end);
+    return res => sendJSON(res, askres, end)
   } else {
-    return res => sendOther(format, res, askres, end);
+    return res => sendOther(format, res, askres, end)
   }
 }
 
 function sendSVG(res, askres, end) {
-  askres.setHeader('Content-Type', 'image/svg+xml;charset=utf-8');
-  end(null, {template: streamFromString(res)});
+  askres.setHeader('Content-Type', 'image/svg+xml;charset=utf-8')
+  end(null, { template: streamFromString(res) })
 }
 
 function sendOther(format, res, askres, end) {
-  askres.setHeader('Content-Type', 'image/' + format);
+  askres.setHeader('Content-Type', 'image/' + format)
   svg2img(res, format)
     .then(data => {
-      end(null, {template: streamFromString(data)});
+      end(null, { template: streamFromString(data) })
     })
     .catch(err => {
       // This emits status code 200, though 500 would be preferable.
-      log.error('svg2img error', err);
-      end(null, {template: '500.html'});
+      log.error('svg2img error', err)
+      end(null, { template: '500.html' })
     })
 }
 
 function sendJSON(res, askres, end) {
-  askres.setHeader('Content-Type', 'application/json');
-  askres.setHeader('Access-Control-Allow-Origin', '*');
-  end(null, {template: streamFromString(res)});
+  askres.setHeader('Content-Type', 'application/json')
+  askres.setHeader('Access-Control-Allow-Origin', '*')
+  end(null, { template: streamFromString(res) })
 }
 
 module.exports = {
-  makeSend
-};
+  makeSend,
+}
diff --git a/lib/server-config.js b/lib/server-config.js
index d4d6af3db66d72eb6a7a72b4e87ff93f13d2b4b5..e3634df31952f328abbf1f04b83ae5c37af80f4a 100644
--- a/lib/server-config.js
+++ b/lib/server-config.js
@@ -1,34 +1,38 @@
-'use strict';
+'use strict'
 
 // This file should only be required by server.js. To simplify testing, config
 // should be injected into other components needing it.
 
-const url = require('url');
-const envFlag = require('node-env-flag');
-const defaults = require('./defaults');
+const url = require('url')
+const envFlag = require('node-env-flag')
+const defaults = require('./defaults')
 
 function envArray(envVar, defaultValue, delimiter) {
-  delimiter = delimiter || ',';
+  delimiter = delimiter || ','
   if (envVar) {
-    return envVar.split(delimiter);
+    return envVar.split(delimiter)
   } else {
-    return defaultValue;
+    return defaultValue
   }
 }
 
-const isSecure = envFlag(process.env.HTTPS, false);
-const port = +process.env.PORT || +process.argv[2] || (isSecure ? 443 : 80);
-const address = process.env.BIND_ADDRESS || process.argv[3] || '::';
+const isSecure = envFlag(process.env.HTTPS, false)
+const port = +process.env.PORT || +process.argv[2] || (isSecure ? 443 : 80)
+const address = process.env.BIND_ADDRESS || process.argv[3] || '::'
 const baseUri = url.format({
   protocol: isSecure ? 'https' : 'http',
   hostname: address,
   port,
   pathname: '/',
-});
+})
 
 // The base URI provides a suitable value for development. Production should
 // configure this.
-const allowedOrigin = envArray(process.env.ALLOWED_ORIGIN, baseUri.replace(/\/$/, ''), ',');
+const allowedOrigin = envArray(
+  process.env.ALLOWED_ORIGIN,
+  baseUri.replace(/\/$/, ''),
+  ','
+)
 
 const config = {
   bind: {
@@ -66,10 +70,10 @@ const config = {
   },
   rateLimit: envFlag(process.env.RATE_LIMIT, true),
   handleInternalErrors: envFlag(process.env.HANDLE_INTERNAL_ERRORS, true),
-};
+}
 
 if (config.font.fallbackPath) {
-  console.log('FALLBACK_FONT_PATH is deprecated. Please use FONT_PATH.');
+  console.log('FALLBACK_FONT_PATH is deprecated. Please use FONT_PATH.')
 }
 
-module.exports = config;
+module.exports = config
diff --git a/lib/server-secrets.js b/lib/server-secrets.js
index f5205cfdfa42475db0de482aecd521a482607bfe..d06c3ff60a0ef4703faa40fd0aa22301173cdf18 100644
--- a/lib/server-secrets.js
+++ b/lib/server-secrets.js
@@ -1,20 +1,22 @@
-'use strict';
+'use strict'
 
 // Everything that cannot be checked in but is useful server-side is stored in
 // a JSON data file: private/secret.json.
 
-const fs = require('fs');
-const path = require('path');
+const fs = require('fs')
+const path = require('path')
 
-const secretsPath = path.join(__dirname, '..', 'private', 'secret.json');
+const secretsPath = path.join(__dirname, '..', 'private', 'secret.json')
 
 if (fs.existsSync(secretsPath)) {
   try {
-    module.exports = require(secretsPath);
-  } catch(e) {
-    console.error(`Error loading secret data: ${e.message}`);
-    process.exit(1);
+    module.exports = require(secretsPath)
+  } catch (e) {
+    console.error(`Error loading secret data: ${e.message}`)
+    process.exit(1)
   }
 } else {
-  console.warn(`No secret data found at ${secretsPath} (see lib/server-secrets.js)`);
+  console.warn(
+    `No secret data found at ${secretsPath} (see lib/server-secrets.js)`
+  )
 }
diff --git a/lib/service-test-runner/cli.js b/lib/service-test-runner/cli.js
index fbb5db80553d41b7adb3759f99e51fc8c3e7a0e7..9336f1b0d93075a00fd96d9abd63fece564d9282 100644
--- a/lib/service-test-runner/cli.js
+++ b/lib/service-test-runner/cli.js
@@ -43,52 +43,60 @@
 //    Relying on npm scripts is safer. Using "pre" makes it impossible to run
 //    the second step without the first.
 
-'use strict';
+'use strict'
 
-const minimist = require('minimist');
-const readAllStdinSync = require('read-all-stdin-sync');
-const Runner = require('./runner');
-const serverHelpers = require('../../lib/in-process-server-test-helpers');
+const minimist = require('minimist')
+const readAllStdinSync = require('read-all-stdin-sync')
+const Runner = require('./runner')
+const serverHelpers = require('../../lib/in-process-server-test-helpers')
 
-require('../../lib/unhandled-rejection.spec');
+require('../../lib/unhandled-rejection.spec')
 
-let server;
-before('Start running the server', function () {
-  this.timeout(5000);
-  server = serverHelpers.start();
-});
-after('Shut down the server', function () { serverHelpers.stop(server); });
+let server
+before('Start running the server', function() {
+  this.timeout(5000)
+  server = serverHelpers.start()
+})
+after('Shut down the server', function() {
+  serverHelpers.stop(server)
+})
 
-const runner = new Runner();
-runner.prepare();
+const runner = new Runner()
+runner.prepare()
 // The server's request cache causes side effects between tests.
-runner.beforeEach = () => { serverHelpers.reset(server); };
+runner.beforeEach = () => {
+  serverHelpers.reset(server)
+}
 
-const args = minimist(process.argv.slice(3));
-const stdinOption = args.stdin;
-const onlyOption = args.only;
+const args = minimist(process.argv.slice(3))
+const stdinOption = args.stdin
+const onlyOption = args.only
 
-let onlyServices;
+let onlyServices
 
 if (stdinOption && onlyOption) {
-  console.error('Do not use --only with --stdin');
+  console.error('Do not use --only with --stdin')
 } else if (stdinOption) {
-  const allStdin = readAllStdinSync().trim();
-  onlyServices = allStdin ? allStdin.split('\n') : [];
+  const allStdin = readAllStdinSync().trim()
+  onlyServices = allStdin ? allStdin.split('\n') : []
 } else if (onlyOption) {
-  onlyServices = onlyOption.split(',');
+  onlyServices = onlyOption.split(',')
 }
 
 if (typeof onlyServices === 'undefined') {
-  console.info('Running all service tests.');
+  console.info('Running all service tests.')
 } else if (onlyServices.length === 0) {
-  console.info('No service tests to run. Exiting.');
-  process.exit(0);
+  console.info('No service tests to run. Exiting.')
+  process.exit(0)
 } else {
-  console.info(`Running tests for ${onlyServices.length} services: ${onlyServices.join(', ')}.\n`);
-  runner.only(onlyServices);
+  console.info(
+    `Running tests for ${onlyServices.length} services: ${onlyServices.join(
+      ', '
+    )}.\n`
+  )
+  runner.only(onlyServices)
 }
 
-runner.toss();
+runner.toss()
 // Invoke run() asynchronously, because Mocha will not start otherwise.
-process.nextTick(run);
+process.nextTick(run)
diff --git a/lib/service-test-runner/infer-pull-request.js b/lib/service-test-runner/infer-pull-request.js
index ec17d2793b369dd35812276e070acacbd36a30d9..2b64e92f5a3a604a32c9daef4479f3a1f7d9f972 100644
--- a/lib/service-test-runner/infer-pull-request.js
+++ b/lib/service-test-runner/infer-pull-request.js
@@ -1,26 +1,30 @@
-'use strict';
+'use strict'
 
-const { parse: urlParse, format: urlFormat } = require('url');
+const { parse: urlParse, format: urlFormat } = require('url')
 
 function formatSlug(owner, repo, pullRequest) {
-  return `${owner}/${repo}#${pullRequest}`;
+  return `${owner}/${repo}#${pullRequest}`
 }
 
 function parseGithubPullRequestUrl(url, options = {}) {
-  const { verifyBaseUrl } = options;
+  const { verifyBaseUrl } = options
 
-  const parsed = urlParse(url);
-  const components = parsed.path.substr(1).split('/');
+  const parsed = urlParse(url)
+  const components = parsed.path.substr(1).split('/')
   if (components[2] !== 'pull' || components.length !== 4) {
-    throw Error(`Invalid GitHub pull request URL: ${url}`);
+    throw Error(`Invalid GitHub pull request URL: ${url}`)
   }
-  const [owner, repo, , pullRequest] = components;
+  const [owner, repo, , pullRequest] = components
 
-  delete parsed.pathname;
-  const baseUrl = urlFormat(parsed, { auth: false, fragment: false, search: false });
+  delete parsed.pathname
+  const baseUrl = urlFormat(parsed, {
+    auth: false,
+    fragment: false,
+    search: false,
+  })
 
   if (verifyBaseUrl && baseUrl !== verifyBaseUrl) {
-    throw Error(`Expected base URL to be ${verifyBaseUrl} but got ${baseUrl}`);
+    throw Error(`Expected base URL to be ${verifyBaseUrl} but got ${baseUrl}`)
   }
 
   return {
@@ -29,42 +33,46 @@ function parseGithubPullRequestUrl(url, options = {}) {
     repo,
     pullRequest: +pullRequest,
     slug: formatSlug(owner, repo, pullRequest),
-  };
+  }
 }
 
 function parseGithubRepoSlug(slug) {
-  const components = slug.split('/');
+  const components = slug.split('/')
   if (components.length !== 2) {
-    throw Error(`Invalid GitHub repo slug: ${slug}`);
+    throw Error(`Invalid GitHub repo slug: ${slug}`)
   }
-  const [owner, repo] = components;
-  return { owner, repo };
+  const [owner, repo] = components
+  return { owner, repo }
 }
 
 function _inferPullRequestFromTravisEnv(env) {
-  const { owner, repo } = parseGithubRepoSlug(env.TRAVIS_REPO_SLUG);
-  const pullRequest = +env.TRAVIS_PULL_REQUEST;
+  const { owner, repo } = parseGithubRepoSlug(env.TRAVIS_REPO_SLUG)
+  const pullRequest = +env.TRAVIS_PULL_REQUEST
   return {
     owner,
     repo,
     pullRequest,
     slug: formatSlug(owner, repo, pullRequest),
-  };
+  }
 }
 
 function _inferPullRequestFromCircleEnv(env) {
-  return parseGithubPullRequestUrl(env.CI_PULL_REQUEST);
+  return parseGithubPullRequestUrl(env.CI_PULL_REQUEST)
 }
 
 function inferPullRequest(env = process.env) {
   if (env.TRAVIS) {
-    return _inferPullRequestFromTravisEnv(env);
+    return _inferPullRequestFromTravisEnv(env)
   } else if (env.CIRCLECI) {
-    return _inferPullRequestFromCircleEnv(env);
+    return _inferPullRequestFromCircleEnv(env)
   } else if (env.CI) {
-    throw Error('Unsupported CI system. Unable to obtain pull request information from the environment.');
+    throw Error(
+      'Unsupported CI system. Unable to obtain pull request information from the environment.'
+    )
   } else {
-    throw Error('Unable to obtain pull request information from the environment. Is this running in CI?');
+    throw Error(
+      'Unable to obtain pull request information from the environment. Is this running in CI?'
+    )
   }
 }
 
@@ -72,4 +80,4 @@ module.exports = {
   parseGithubPullRequestUrl,
   parseGithubRepoSlug,
   inferPullRequest,
-};
+}
diff --git a/lib/service-test-runner/infer-pull-request.spec.js b/lib/service-test-runner/infer-pull-request.spec.js
index 553924d5b5aed149c4b740d6a8b5b2e895bd1d80..e3f46d3255593fb0568c562fddff6254cb85ae91 100644
--- a/lib/service-test-runner/infer-pull-request.spec.js
+++ b/lib/service-test-runner/infer-pull-request.spec.js
@@ -1,27 +1,32 @@
-'use strict';
+'use strict'
 
-const { test, given, forCases } = require('sazerac');
+const { test, given, forCases } = require('sazerac')
 const {
   parseGithubPullRequestUrl,
   inferPullRequest,
-} = require('./infer-pull-request');
+} = require('./infer-pull-request')
 
 describe('Pull request inference', function() {
   test(parseGithubPullRequestUrl, () => {
     forCases([
       given('https://github.com/badges/shields/pull/1234'),
-      given('https://github.com/badges/shields/pull/1234', { verifyBaseUrl: 'https://github.com' }),
+      given('https://github.com/badges/shields/pull/1234', {
+        verifyBaseUrl: 'https://github.com',
+      }),
     ]).expect({
       baseUrl: 'https://github.com',
       owner: 'badges',
       repo: 'shields',
       pullRequest: 1234,
       slug: 'badges/shields#1234',
-    });
+    })
 
-    given('https://github.com/badges/shields/pull/1234', { verifyBaseUrl: 'https://example.com' })
-      .expectError('Expected base URL to be https://example.com but got https://github.com');
-  });
+    given('https://github.com/badges/shields/pull/1234', {
+      verifyBaseUrl: 'https://example.com',
+    }).expectError(
+      'Expected base URL to be https://example.com but got https://github.com'
+    )
+  })
 
   test(inferPullRequest, () => {
     const expected = {
@@ -29,17 +34,17 @@ describe('Pull request inference', function() {
       repo: 'shields',
       pullRequest: 1234,
       slug: 'badges/shields#1234',
-    };
+    }
 
     given({
       CIRCLECI: '1',
       CI_PULL_REQUEST: 'https://github.com/badges/shields/pull/1234',
-    }).expect(Object.assign({ baseUrl: 'https://github.com' }, expected));
+    }).expect(Object.assign({ baseUrl: 'https://github.com' }, expected))
 
     given({
       TRAVIS: '1',
       TRAVIS_REPO_SLUG: 'badges/shields',
       TRAVIS_PULL_REQUEST: '1234',
-    }).expect(expected);
-  });
-});
+    }).expect(expected)
+  })
+})
diff --git a/lib/service-test-runner/pull-request-services-cli.js b/lib/service-test-runner/pull-request-services-cli.js
index ec20dd6c8c23c747c231b3b9a964632501579d37..0818f21b235e5352270c757cb926aff940d70e9e 100644
--- a/lib/service-test-runner/pull-request-services-cli.js
+++ b/lib/service-test-runner/pull-request-services-cli.js
@@ -13,44 +13,46 @@
 //
 // TRAVIS=1 TRAVIS_REPO_SLUG=badges/shields TRAVIS_PULL_REQUEST=1108 npm run test:services:pr:prepare
 
-'use strict';
+'use strict'
 
-const fetch = require('node-fetch');
-const { inferPullRequest } = require('./infer-pull-request');
-const servicesForTitle = require('./services-for-title');
+const fetch = require('node-fetch')
+const { inferPullRequest } = require('./infer-pull-request')
+const servicesForTitle = require('./services-for-title')
 
-async function getTitle (owner, repo, pullRequest) {
-  let uri = `https://api.github.com/repos/${owner}/${repo}/pulls/${pullRequest}`;
+async function getTitle(owner, repo, pullRequest) {
+  let uri = `https://api.github.com/repos/${owner}/${repo}/pulls/${pullRequest}`
   if (process.env.GITHUB_TOKEN) {
-    uri += `?access_token=${process.env.GITHUB_TOKEN}`;
+    uri += `?access_token=${process.env.GITHUB_TOKEN}`
   }
-  const options = { headers: { 'User-Agent': 'badges/shields' } };
-  const res = await fetch(uri, options);
-  if (! res.ok) {
-    throw Error(`${res.status} ${res.statusText}`);
+  const options = { headers: { 'User-Agent': 'badges/shields' } }
+  const res = await fetch(uri, options)
+  if (!res.ok) {
+    throw Error(`${res.status} ${res.statusText}`)
   }
 
-  const { title } = await res.json();
-  return title;
+  const { title } = await res.json()
+  return title
 }
 
 async function main() {
-  const { owner, repo, pullRequest, slug } = inferPullRequest();
-  console.error(`PR: ${slug}`);
+  const { owner, repo, pullRequest, slug } = inferPullRequest()
+  console.error(`PR: ${slug}`)
 
-  const title = await getTitle(owner, repo, pullRequest);
+  const title = await getTitle(owner, repo, pullRequest)
 
-  console.error(`Title: ${title}\n`);
-  const services = servicesForTitle(title);
+  console.error(`Title: ${title}\n`)
+  const services = servicesForTitle(title)
   if (services.length === 0) {
-    console.error('No services found. Nothing to do.');
+    console.error('No services found. Nothing to do.')
   } else {
-    console.error(`Services: (${services.length} found) ${services.join(', ')}\n`);
-    console.log(services.join('\n'));
+    console.error(
+      `Services: (${services.length} found) ${services.join(', ')}\n`
+    )
+    console.log(services.join('\n'))
   }
 }
 
-(async () => {
+;(async () => {
   try {
     await main()
   } catch (e) {
diff --git a/lib/service-test-runner/runner.js b/lib/service-test-runner/runner.js
index 60096a16ebe288309a59452502f381e8ba63e3b2..59fdf93bd3c02b1c5eaac0a54e71c3ef99c10421 100644
--- a/lib/service-test-runner/runner.js
+++ b/lib/service-test-runner/runner.js
@@ -1,6 +1,6 @@
-'use strict';
+'use strict'
 
-const { loadTesters } = require('../../services');
+const { loadTesters } = require('../../services')
 
 /**
  * Load a collection of ServiceTester objects and register them with Mocha.
@@ -10,20 +10,22 @@ class Runner {
    * Function to invoke before each test. This is a stub which can be
    * overridden on instances.
    */
-  beforeEach () {}
+  beforeEach() {}
 
   /**
    * Prepare the runner by loading up all the ServiceTester objects.
    */
-  prepare () {
-    this.testers = loadTesters();
+  prepare() {
+    this.testers = loadTesters()
     this.testers.forEach(tester => {
-      tester.beforeEach = () => { this.beforeEach(); };
-    });
+      tester.beforeEach = () => {
+        this.beforeEach()
+      }
+    })
   }
 
-  _testersForService (service) {
-    return this.testers.filter(t => t.id.toLowerCase() === service);
+  _testersForService(service) {
+    return this.testers.filter(t => t.id.toLowerCase() === service)
   }
 
   /**
@@ -31,31 +33,35 @@ class Runner {
    *
    * @param services An array of service ids to run
    */
-  only (services) {
-    const normalizedServices = new Set(services.map(v => v.toLowerCase()));
+  only(services) {
+    const normalizedServices = new Set(services.map(v => v.toLowerCase()))
 
-    const missingServices = [];
+    const missingServices = []
     normalizedServices.forEach(service => {
-      const testers = this._testersForService(service);
+      const testers = this._testersForService(service)
 
       if (testers.length === 0) {
-        missingServices.push(service);
+        missingServices.push(service)
       }
 
-      testers.forEach(tester => { tester.only(); });
-    });
+      testers.forEach(tester => {
+        tester.only()
+      })
+    })
 
     // Throw at the end, to provide a better error message.
     if (missingServices.length > 0) {
-      throw Error('Unknown services: ' + missingServices.join(', '));
+      throw Error('Unknown services: ' + missingServices.join(', '))
     }
   }
 
   /**
    * Register the tests with Mocha.
    */
-  toss () {
-    this.testers.forEach(tester => { tester.toss(); });
+  toss() {
+    this.testers.forEach(tester => {
+      tester.toss()
+    })
   }
 }
-module.exports = Runner;
+module.exports = Runner
diff --git a/lib/service-test-runner/services-for-title.js b/lib/service-test-runner/services-for-title.js
index cf56ae52c958969625996d96f77146a9199506c7..59bbf0bdb43124e3f38cd111c29071f6753bccb5 100644
--- a/lib/service-test-runner/services-for-title.js
+++ b/lib/service-test-runner/services-for-title.js
@@ -1,21 +1,21 @@
-'use strict';
+'use strict'
 
-const difference = require('lodash.difference');
+const difference = require('lodash.difference')
 
 function servicesForTitle(title) {
-  const bracketed = /\[([^\]]+)\]/g;
+  const bracketed = /\[([^\]]+)\]/g
 
-  const preNormalized = title.toLowerCase();
+  const preNormalized = title.toLowerCase()
 
-  let services = [];
-  let match;
+  let services = []
+  let match
   while ((match = bracketed.exec(preNormalized))) {
-    const [, bracketed] = match;
-    services = services.concat(bracketed.split(' '));
+    const [, bracketed] = match
+    services = services.concat(bracketed.split(' '))
   }
 
-  const blacklist = ['wip', 'rfc'];
-  return difference(services.map(service => service.toLowerCase()), blacklist);
+  const blacklist = ['wip', 'rfc']
+  return difference(services.map(service => service.toLowerCase()), blacklist)
 }
 
-module.exports = servicesForTitle;
+module.exports = servicesForTitle
diff --git a/lib/service-test-runner/services-for-title.spec.js b/lib/service-test-runner/services-for-title.spec.js
index 902f9012e207e5cdad98f90b95f0fcb3d46af6ad..ac0f0d5cdae32e7df3caeedde4e29808e1d75033 100644
--- a/lib/service-test-runner/services-for-title.spec.js
+++ b/lib/service-test-runner/services-for-title.spec.js
@@ -1,23 +1,19 @@
-'use strict';
+'use strict'
 
-const { test, given } = require('sazerac');
-const servicesForTitle = require('./services-for-title');
+const { test, given } = require('sazerac')
+const servicesForTitle = require('./services-for-title')
 
 describe('Services from PR title', function() {
   test(servicesForTitle, () => {
-    given('[Travis] Fix timeout issues').expect(['travis']);
+    given('[Travis] Fix timeout issues').expect(['travis'])
     given('[Travis Sonar] Support user token authentication').expect([
       'travis',
       'sonar',
-    ]);
-    given('[CRAN CPAN CTAN] Add test coverage').expect([
-      'cran',
-      'cpan',
-      'ctan',
-    ]);
+    ])
+    given('[CRAN CPAN CTAN] Add test coverage').expect(['cran', 'cpan', 'ctan'])
     given(
       '[RFC] Add Joi-based request validation to BaseJsonService and rewrite [NPM] badges'
-    ).expect(['npm']);
-    given('make changes to [CRAN] and [CPAN]').expect(['cran', 'cpan']);
-  });
-});
+    ).expect(['npm'])
+    given('make changes to [CRAN] and [CPAN]').expect(['cran', 'cpan'])
+  })
+})
diff --git a/lib/suggest.js b/lib/suggest.js
index 24cd23462fa22fd768c02b03667a667025ab7121..937a156acc27be688db6dbe6defba96089827563 100644
--- a/lib/suggest.js
+++ b/lib/suggest.js
@@ -1,7 +1,7 @@
-'use strict';
+'use strict'
 
-const nodeUrl = require('url');
-const request = require('request');
+const nodeUrl = require('url')
+const request = require('request')
 
 // data: {url}, JSON-serializable object.
 // end: function(json), with json of the form:
@@ -9,130 +9,149 @@ const request = require('request');
 //    - link: target as a string URL.
 //    - badge: shields image URL.
 //    - name: string
-function suggest (allowedOrigin, githubApiProvider, data, end, ask) {
+function suggest(allowedOrigin, githubApiProvider, data, end, ask) {
   // The typical dev and production setups are cross-origin. However, in
   // Heroku deploys and some self-hosted deploys these requests may come from
   // the same host.
-  const origin = ask.req.headers.origin;
+  const origin = ask.req.headers.origin
   if (origin) {
     if (allowedOrigin.includes(origin)) {
-      ask.res.setHeader('Access-Control-Allow-Origin', origin);
+      ask.res.setHeader('Access-Control-Allow-Origin', origin)
     } else {
-      ask.res.setHeader('Access-Control-Allow-Origin', 'null');
-      end({err: 'Disallowed'});
-      return;
+      ask.res.setHeader('Access-Control-Allow-Origin', 'null')
+      end({ err: 'Disallowed' })
+      return
     }
   }
 
-  let url;
+  let url
   try {
-    url = nodeUrl.parse(data.url);
-  } catch(e) { end({err: ''+e}); return; }
-  findSuggestions(githubApiProvider, url, end);
+    url = nodeUrl.parse(data.url)
+  } catch (e) {
+    end({ err: '' + e })
+    return
+  }
+  findSuggestions(githubApiProvider, url, end)
 }
 
 // url: string
 // cb: function({badges})
-function findSuggestions (githubApiProvider, url, cb) {
-  let promises = [];
+function findSuggestions(githubApiProvider, url, cb) {
+  let promises = []
   if (url.hostname === 'github.com') {
-    const userRepo = url.pathname.slice(1).split('/');
-    const user = userRepo[0];
-    const repo = userRepo[1];
+    const userRepo = url.pathname.slice(1).split('/')
+    const user = userRepo[0]
+    const repo = userRepo[1]
     promises = promises.concat([
       githubIssues(user, repo),
       githubForks(user, repo),
       githubStars(user, repo),
       githubLicense(githubApiProvider, user, repo),
-    ]);
+    ])
   }
-  promises.push(twitterPage(url));
-  Promise.all(promises).then(function(badges) {
-    // eslint-disable-next-line standard/no-callback-literal
-    cb({badges: badges.filter(function(b) { return b != null; })});
-  }).catch(function(err) {
-    // eslint-disable-next-line standard/no-callback-literal
-    cb({badges: [], err: err});
-  });
+  promises.push(twitterPage(url))
+  Promise.all(promises)
+    .then(function(badges) {
+      // eslint-disable-next-line standard/no-callback-literal
+      cb({
+        badges: badges.filter(function(b) {
+          return b != null
+        }),
+      })
+    })
+    .catch(function(err) {
+      // eslint-disable-next-line standard/no-callback-literal
+      cb({ badges: [], err: err })
+    })
 }
 
-function twitterPage (url) {
-  if (url.protocol === null) { return Promise.resolve(null); }
-  const schema = url.protocol.slice(0, -1);
-  const host = url.host;
-  const path = url.path;
+function twitterPage(url) {
+  if (url.protocol === null) {
+    return Promise.resolve(null)
+  }
+  const schema = url.protocol.slice(0, -1)
+  const host = url.host
+  const path = url.path
   return Promise.resolve({
     name: 'Twitter',
-    link: 'https://twitter.com/intent/tweet?text=Wow:&url=' + encodeURIComponent(url.href),
-    badge: 'https://img.shields.io/twitter/url/' + schema + '/' + host + path + '.svg?style=social',
-  });
+    link:
+      'https://twitter.com/intent/tweet?text=Wow:&url=' +
+      encodeURIComponent(url.href),
+    badge:
+      'https://img.shields.io/twitter/url/' +
+      schema +
+      '/' +
+      host +
+      path +
+      '.svg?style=social',
+  })
 }
 
-function githubIssues (user, repo) {
-  const userRepo = user + '/' + repo;
+function githubIssues(user, repo) {
+  const userRepo = user + '/' + repo
   return Promise.resolve({
     name: 'GitHub issues',
     link: 'https://github.com/' + userRepo + '/issues',
     badge: 'https://img.shields.io/github/issues/' + userRepo + '.svg',
-  });
+  })
 }
 
-function githubForks (user, repo) {
-  const userRepo = user + '/' + repo;
+function githubForks(user, repo) {
+  const userRepo = user + '/' + repo
   return Promise.resolve({
     name: 'GitHub forks',
     link: 'https://github.com/' + userRepo + '/network',
     badge: 'https://img.shields.io/github/forks/' + userRepo + '.svg',
-  });
+  })
 }
 
-function githubStars (user, repo) {
-  const userRepo = user + '/' + repo;
+function githubStars(user, repo) {
+  const userRepo = user + '/' + repo
   return Promise.resolve({
     name: 'GitHub stars',
     link: 'https://github.com/' + userRepo + '/stargazers',
     badge: 'https://img.shields.io/github/stars/' + userRepo + '.svg',
-  });
+  })
 }
 
-function githubLicense (githubApiProvider, user, repo) {
-  return new Promise((resolve) => {
-    const apiUrl = `/repos/${user}/${repo}/license`;
+function githubLicense(githubApiProvider, user, repo) {
+  return new Promise(resolve => {
+    const apiUrl = `/repos/${user}/${repo}/license`
     githubApiProvider.request(request, apiUrl, {}, function(err, res, buffer) {
       if (err !== null) {
-        resolve(null);
-        return;
+        resolve(null)
+        return
       }
       const defaultBadge = {
         name: 'GitHub license',
         link: `https://github.com/${user}/${repo}`,
-        badge: `https://img.shields.io/github/license/${user}/${repo}.svg`
-      };
+        badge: `https://img.shields.io/github/license/${user}/${repo}.svg`,
+      }
       if (res.statusCode !== 200) {
-        resolve(defaultBadge);
+        resolve(defaultBadge)
       }
       try {
-        const data = JSON.parse(buffer);
+        const data = JSON.parse(buffer)
         if (data.html_url) {
-          defaultBadge.link = data.html_url;
-          resolve(defaultBadge);
+          defaultBadge.link = data.html_url
+          resolve(defaultBadge)
         } else {
-          resolve(defaultBadge);
+          resolve(defaultBadge)
         }
-      } catch(e) {
-        resolve(defaultBadge);
+      } catch (e) {
+        resolve(defaultBadge)
       }
     })
-  });
+  })
 }
 
-function setRoutes (allowedOrigin, githubApiProvider, server) {
-  server.ajax.on(
-    'suggest/v1',
-    (data, end, ask) => suggest(allowedOrigin, githubApiProvider, data, end, ask));
+function setRoutes(allowedOrigin, githubApiProvider, server) {
+  server.ajax.on('suggest/v1', (data, end, ask) =>
+    suggest(allowedOrigin, githubApiProvider, data, end, ask)
+  )
 }
 
 module.exports = {
   suggest,
   setRoutes,
-};
+}
diff --git a/lib/svg-badge-parser.js b/lib/svg-badge-parser.js
index 81c4f7434993d255674ce634d25da86074913a09..bd26d9f2293513afe04aeea2069c68f3f83bfe69 100644
--- a/lib/svg-badge-parser.js
+++ b/lib/svg-badge-parser.js
@@ -1,20 +1,20 @@
-'use strict';
+'use strict'
 
-const nodeifySync = require('./nodeify-sync');
+const nodeifySync = require('./nodeify-sync')
 
-const leadingWhitespace = /(?:\r\n\s*|\r\s*|\n\s*)/g;
-const getValue = />([^<>]+)<\/text><\/g>/;
+const leadingWhitespace = /(?:\r\n\s*|\r\s*|\n\s*)/g
+const getValue = />([^<>]+)<\/text><\/g>/
 
 function valueFromSvgBadge(svg) {
   if (typeof svg !== 'string') {
-    throw TypeError('Parameter should be a string');
+    throw TypeError('Parameter should be a string')
   }
-  const stripped = svg.replace(leadingWhitespace, '');
-  const match = getValue.exec(stripped);
+  const stripped = svg.replace(leadingWhitespace, '')
+  const match = getValue.exec(stripped)
   if (match) {
-    return match[1];
+    return match[1]
   } else {
-    throw Error(`Can't get value from SVG:\n${svg}`);
+    throw Error(`Can't get value from SVG:\n${svg}`)
   }
 }
 
@@ -23,14 +23,14 @@ function valueFromSvgBadge(svg) {
 function fetchFromSvg(request, url, cb) {
   request(url, function(err, res, buffer) {
     if (err !== null) {
-      cb(err);
+      cb(err)
     } else {
-      nodeifySync(() => valueFromSvgBadge(buffer), cb);
+      nodeifySync(() => valueFromSvgBadge(buffer), cb)
     }
-  });
+  })
 }
 
 module.exports = {
   valueFromSvgBadge,
-  fetchFromSvg
-};
+  fetchFromSvg,
+}
diff --git a/lib/svg-badge-parser.spec.js b/lib/svg-badge-parser.spec.js
index b807e938f823fcb8a3ae13e215f65745ce112c1b..abff3a46390f3fb872f3bd52031e667cc78bad8a 100644
--- a/lib/svg-badge-parser.spec.js
+++ b/lib/svg-badge-parser.spec.js
@@ -1,19 +1,19 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const { makeBadgeData } = require('./badge-data');
-const { valueFromSvgBadge } = require('./svg-badge-parser');
-const testHelpers = require('./make-badge-test-helpers');
+const { expect } = require('chai')
+const { makeBadgeData } = require('./badge-data')
+const { valueFromSvgBadge } = require('./svg-badge-parser')
+const testHelpers = require('./make-badge-test-helpers')
 
-const makeBadge = testHelpers.makeBadge();
+const makeBadge = testHelpers.makeBadge()
 
 describe('The SVG badge parser', function() {
   it('should find the correct value', function() {
-    const badgeData = makeBadgeData('this is the label', {});
-    badgeData.text[1] = 'this is the result!';
+    const badgeData = makeBadgeData('this is the label', {})
+    badgeData.text[1] = 'this is the result!'
 
-    const exampleSvg = makeBadge(badgeData);
+    const exampleSvg = makeBadge(badgeData)
 
-    expect(valueFromSvgBadge(exampleSvg)).to.equal('this is the result!');
-  });
-});
+    expect(valueFromSvgBadge(exampleSvg)).to.equal('this is the result!')
+  })
+})
diff --git a/lib/svg-to-img.js b/lib/svg-to-img.js
index 3b4a55387b9c241fe842a557b64ba59d9ce546d5..979272d457d30aaf933e2a50adffa0c44b29ac45 100644
--- a/lib/svg-to-img.js
+++ b/lib/svg-to-img.js
@@ -1,41 +1,43 @@
-'use strict';
+'use strict'
 
-const gm = require('gm');
-const LruCache = require('./lru-cache');
+const gm = require('gm')
+const LruCache = require('./lru-cache')
 
-const imageMagick = gm.subClass({ imageMagick: true });
+const imageMagick = gm.subClass({ imageMagick: true })
 
 // The following is an arbitrary limit (~1.5MB, 1.5kB/image).
-const imgCache = new LruCache(1000);
+const imgCache = new LruCache(1000)
 
-function svgToImg (svg, format) {
+function svgToImg(svg, format) {
   return new Promise((resolve, reject) => {
-    const cacheIndex = format + svg;
+    const cacheIndex = format + svg
     if (imgCache.has(cacheIndex)) {
       // We own a cache for this svg conversion.
-      const result = imgCache.get(cacheIndex);
-      resolve(result);
-      return;
+      const result = imgCache.get(cacheIndex)
+      resolve(result)
+      return
     }
 
-    const buf = Buffer.from('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + svg);
+    const buf = Buffer.from(
+      '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + svg
+    )
     imageMagick(buf, 'image.' + format)
       .density(90)
       .background(format === 'jpg' ? '#FFFFFF' : 'none')
       .flatten()
       .toBuffer(format, (err, data) => {
         if (err) {
-          reject(err);
+          reject(err)
         } else {
-          imgCache.set(cacheIndex, data);
-          resolve(data);
+          imgCache.set(cacheIndex, data)
+          resolve(data)
         }
-      });
-  });
-};
+      })
+  })
+}
 
-module.exports = svgToImg;
+module.exports = svgToImg
 
 // To simplify testing.
-module.exports._imgCache = imgCache;
-module.exports._imageMagick = imageMagick;
+module.exports._imgCache = imgCache
+module.exports._imageMagick = imageMagick
diff --git a/lib/svg-to-img.spec.js b/lib/svg-to-img.spec.js
index 55a4a0055c929f1535f8d65d77ad486953aa16b8..d87f9370b346b39b48ec0b083951280e47765307 100644
--- a/lib/svg-to-img.spec.js
+++ b/lib/svg-to-img.spec.js
@@ -1,31 +1,35 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const isPng = require('is-png');
-const sinon = require('sinon');
-const svg2img = require('./svg-to-img');
-const testHelpers = require('./make-badge-test-helpers');
+const { expect } = require('chai')
+const isPng = require('is-png')
+const sinon = require('sinon')
+const svg2img = require('./svg-to-img')
+const testHelpers = require('./make-badge-test-helpers')
 
-const makeBadge = testHelpers.makeBadge();
+const makeBadge = testHelpers.makeBadge()
 
-describe('The rasterizer', function () {
-  let cacheGet;
-  beforeEach(function () { cacheGet = sinon.spy(svg2img._imgCache, 'get'); });
-  afterEach(function () { cacheGet.restore(); });
+describe('The rasterizer', function() {
+  let cacheGet
+  beforeEach(function() {
+    cacheGet = sinon.spy(svg2img._imgCache, 'get')
+  })
+  afterEach(function() {
+    cacheGet.restore()
+  })
 
   it('should produce PNG', async function() {
-    const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' });
-    const data = await svg2img(svg, 'png');
-    expect(data).to.satisfy(isPng);
-  });
+    const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' })
+    const data = await svg2img(svg, 'png')
+    expect(data).to.satisfy(isPng)
+  })
 
   it('should cache its results', async function() {
-    const svg = makeBadge({ text: ['will-this', 'be-cached?'], format: 'svg' });
-    const data1 = await svg2img(svg, 'png');
-    expect(data1).to.satisfy(isPng);
-    expect(cacheGet).not.to.have.been.called;
+    const svg = makeBadge({ text: ['will-this', 'be-cached?'], format: 'svg' })
+    const data1 = await svg2img(svg, 'png')
+    expect(data1).to.satisfy(isPng)
+    expect(cacheGet).not.to.have.been.called
     const data2 = await svg2img(svg, 'png')
-    expect(data2).to.satisfy(isPng);
-    expect(cacheGet).to.have.been.calledOnce;
-  });
-});
+    expect(data2).to.satisfy(isPng)
+    expect(cacheGet).to.have.been.calledOnce
+  })
+})
diff --git a/lib/sys/monitor.js b/lib/sys/monitor.js
index 6aa3cf00aacdae693b53da4749ce4a6deb3d57df..0ff815e17eb53a6daf3406bdac52944f1973ec16 100644
--- a/lib/sys/monitor.js
+++ b/lib/sys/monitor.js
@@ -1,69 +1,83 @@
-'use strict';
+'use strict'
 
-const secretIsValid = require('./secret-is-valid');
-const serverSecrets = require('../server-secrets');
-const config = require('../server-config');
-const RateLimit = require('./rate-limit');
-const log = require('../log');
+const secretIsValid = require('./secret-is-valid')
+const serverSecrets = require('../server-secrets')
+const config = require('../server-config')
+const RateLimit = require('./rate-limit')
+const log = require('../log')
 
 function secretInvalid(req, res) {
   if (!secretIsValid(req.password)) {
     // An unknown entity tries to connect. Let the connection linger for a minute.
     setTimeout(function() {
-      res.json({errors: [{code: 'invalid_secrets'}]});
-    }, 10000);
-    return true;
+      res.json({ errors: [{ code: 'invalid_secrets' }] })
+    }, 10000)
+    return true
   }
-  return false;
+  return false
 }
 
 function setRoutes(server) {
   const ipRateLimit = new RateLimit({
     whitelist: /^192\.30\.252\.\d+$/, // Whitelist GitHub IPs.
-  });
-  const badgeTypeRateLimit = new RateLimit({maxHitsPerPeriod: 3000});
+  })
+  const badgeTypeRateLimit = new RateLimit({ maxHitsPerPeriod: 3000 })
   const refererRateLimit = new RateLimit({
     maxHitsPerPeriod: 300,
     whitelist: /^https?:\/\/shields\.io\/$/,
-  });
+  })
 
   server.handle(function monitorHandler(req, res, next) {
     if (req.url.startsWith('/sys/')) {
-      if (secretInvalid(req, res)) { return; }
+      if (secretInvalid(req, res)) {
+        return
+      }
     }
 
     if (config.rateLimit) {
-      const ip = (req.headers['x-forwarded-for'] || '').split(', ')[0]
-        || req.socket.remoteAddress;
-      const badgeType = req.url.split(/[/-]/).slice(0, 3).join('');
-      const referer = req.headers['referer'];
+      const ip =
+        (req.headers['x-forwarded-for'] || '').split(', ')[0] ||
+        req.socket.remoteAddress
+      const badgeType = req.url
+        .split(/[/-]/)
+        .slice(0, 3)
+        .join('')
+      const referer = req.headers['referer']
 
-      if (ipRateLimit.isBanned(ip, req, res)) { return; }
-      if (badgeTypeRateLimit.isBanned(badgeType, req, res)) { return; }
-      if (refererRateLimit.isBanned(referer, req, res)) { return; }
+      if (ipRateLimit.isBanned(ip, req, res)) {
+        return
+      }
+      if (badgeTypeRateLimit.isBanned(badgeType, req, res)) {
+        return
+      }
+      if (refererRateLimit.isBanned(referer, req, res)) {
+        return
+      }
     }
 
-    next();
-  });
+    next()
+  })
 
   server.get('/sys/network', (req, res) => {
-    res.json({ips: serverSecrets.shieldsIps});
-  });
+    res.json({ ips: serverSecrets.shieldsIps })
+  })
 
   server.ws('/sys/logs', socket => {
-    const listener = (...msg) => socket.send(msg.join(' '));
-    socket.on('close', () => log.removeListener(listener));
+    const listener = (...msg) => socket.send(msg.join(' '))
+    socket.on('close', () => log.removeListener(listener))
     socket.on('message', msg => {
-      let req;
+      let req
       try {
-        req = JSON.parse(msg);
-      } catch(e) { return; }
+        req = JSON.parse(msg)
+      } catch (e) {
+        return
+      }
       if (!secretIsValid(req.secret)) {
-        return socket.close();
+        return socket.close()
       }
-      log.addListener(listener);
-    });
-  });
+      log.addListener(listener)
+    })
+  })
 
   server.get('/sys/rate-limit', (req, res) => {
     res.json({
@@ -71,9 +85,9 @@ function setRoutes(server) {
       badgeType: badgeTypeRateLimit.toJSON(),
       referer: refererRateLimit.toJSON(),
     })
-  });
+  })
 }
 
 module.exports = {
   setRoutes,
-};
+}
diff --git a/lib/sys/rate-limit.js b/lib/sys/rate-limit.js
index 063f9bc20b9f1dd56d1f90542171dd7143f8b1d8..8e64f73dd618cd8abda7c81f16305756c53c1671 100644
--- a/lib/sys/rate-limit.js
+++ b/lib/sys/rate-limit.js
@@ -1,44 +1,48 @@
-'use strict';
+'use strict'
 
 // A rate limit ensures that a request parameter gets flagged if it goes
 // above a limit.
 module.exports = class RateLimit {
   constructor(options = {}) {
     // this.hits: Map from request parameters to the number of hits.
-    this.hits = new Map();
-    this.period = options.period || 200;  // 3 min ⅓, in seconds
-    this.maxHitsPerPeriod = options.maxHitsPerPeriod || 500;
-    this.banned = new Set();
-    this.bannedUrls = new Set();
-    this.whitelist = options.whitelist
-      || /(?!)/;  // Matches nothing by default.
-    setInterval(this.resetHits.bind(this), this.period * 1000);
+    this.hits = new Map()
+    this.period = options.period || 200 // 3 min ⅓, in seconds
+    this.maxHitsPerPeriod = options.maxHitsPerPeriod || 500
+    this.banned = new Set()
+    this.bannedUrls = new Set()
+    this.whitelist = options.whitelist || /(?!)/ // Matches nothing by default.
+    setInterval(this.resetHits.bind(this), this.period * 1000)
   }
 
   resetHits() {
-    this.hits.clear();
-    this.banned.clear();
-    this.bannedUrls.clear();
+    this.hits.clear()
+    this.banned.clear()
+    this.bannedUrls.clear()
   }
 
   isBanned(reqParam, req, res) {
-    const hitsInCurrentPeriod = this.hits.get(reqParam) || 0;
-    if ((reqParam != null) && !this.whitelist.test(reqParam)
-      && (hitsInCurrentPeriod > this.maxHitsPerPeriod)) {
-      this.banned.add(reqParam);
+    const hitsInCurrentPeriod = this.hits.get(reqParam) || 0
+    if (
+      reqParam != null &&
+      !this.whitelist.test(reqParam) &&
+      hitsInCurrentPeriod > this.maxHitsPerPeriod
+    ) {
+      this.banned.add(reqParam)
     }
 
     if (this.banned.has(reqParam)) {
-      res.statusCode = 429;
-      res.setHeader('Retry-After', String(this.period));
-      res.end(`Exceeded limit ${this.maxHitsPerPeriod} requests ` +
-        `per ${this.period} seconds`);
-      this.bannedUrls.add(req.url);
-      return true;
+      res.statusCode = 429
+      res.setHeader('Retry-After', String(this.period))
+      res.end(
+        `Exceeded limit ${this.maxHitsPerPeriod} requests ` +
+          `per ${this.period} seconds`
+      )
+      this.bannedUrls.add(req.url)
+      return true
     }
 
-    this.hits.set(reqParam, hitsInCurrentPeriod + 1);
-    return false;
+    this.hits.set(reqParam, hitsInCurrentPeriod + 1)
+    return false
   }
 
   toJSON() {
@@ -46,6 +50,6 @@ module.exports = class RateLimit {
       banned: [...this.banned],
       hits: [...this.hits],
       urls: [...this.bannedUrls],
-    };
+    }
   }
 }
diff --git a/lib/sys/secret-is-valid.js b/lib/sys/secret-is-valid.js
index 57726a7af0910a1edd0f35ef5e4472081a26e94f..0e48081633aee1688632df38c814694807812094 100644
--- a/lib/sys/secret-is-valid.js
+++ b/lib/sys/secret-is-valid.js
@@ -1,18 +1,20 @@
-'use strict';
+'use strict'
 
-const serverSecrets = require('../server-secrets');
+const serverSecrets = require('../server-secrets')
 
 function secretIsValid(secret = '') {
-  return constEq(secret, serverSecrets.shieldsSecret);
+  return constEq(secret, serverSecrets.shieldsSecret)
 }
 
 function constEq(a, b) {
-  if (a.length !== b.length) { return false; }
-  let zero = 0;
+  if (a.length !== b.length) {
+    return false
+  }
+  let zero = 0
   for (let i = 0; i < a.length; i++) {
-    zero |= a.charCodeAt(i) ^ b.charCodeAt(i);
+    zero |= a.charCodeAt(i) ^ b.charCodeAt(i)
   }
-  return (zero === 0);
+  return zero === 0
 }
 
-module.exports = secretIsValid;
+module.exports = secretIsValid
diff --git a/lib/teamcity-badge-helpers.js b/lib/teamcity-badge-helpers.js
index 61095c49882544d4b82c271f39b5360e9ca96dcb..3ee34077302c1935c3ab0fa2751ae1db4f5e3358 100644
--- a/lib/teamcity-badge-helpers.js
+++ b/lib/teamcity-badge-helpers.js
@@ -1,36 +1,47 @@
-'use strict';
+'use strict'
 
-const { makeBadgeData: getBadgeData } = require('./badge-data');
+const { makeBadgeData: getBadgeData } = require('./badge-data')
 
-function teamcityBadge(url, buildId, advanced, format, data, sendBadge, request) {
-  const apiUrl = url + '/app/rest/builds/buildType:(id:' + buildId + ')?guest=1';
-  const badgeData = getBadgeData('build', data);
-  request(apiUrl, { headers: { 'Accept': 'application/json' } }, function(err, res, buffer) {
+function teamcityBadge(
+  url,
+  buildId,
+  advanced,
+  format,
+  data,
+  sendBadge,
+  request
+) {
+  const apiUrl = url + '/app/rest/builds/buildType:(id:' + buildId + ')?guest=1'
+  const badgeData = getBadgeData('build', data)
+  request(apiUrl, { headers: { Accept: 'application/json' } }, function(
+    err,
+    res,
+    buffer
+  ) {
     if (err != null) {
-      badgeData.text[1] = 'inaccessible';
-      sendBadge(format, badgeData);
-      return;
+      badgeData.text[1] = 'inaccessible'
+      sendBadge(format, badgeData)
+      return
     }
     try {
-      const data = JSON.parse(buffer);
+      const data = JSON.parse(buffer)
       if (advanced)
-        badgeData.text[1] = (data.statusText || data.status || '').toLowerCase();
-      else
-        badgeData.text[1] = (data.status || '').toLowerCase();
+        badgeData.text[1] = (data.statusText || data.status || '').toLowerCase()
+      else badgeData.text[1] = (data.status || '').toLowerCase()
       if (data.status === 'SUCCESS') {
-        badgeData.colorscheme = 'brightgreen';
-        badgeData.text[1] = 'passing';
+        badgeData.colorscheme = 'brightgreen'
+        badgeData.text[1] = 'passing'
       } else {
-        badgeData.colorscheme = 'red';
+        badgeData.colorscheme = 'red'
       }
-      sendBadge(format, badgeData);
-    } catch(e) {
-      badgeData.text[1] = 'invalid';
-      sendBadge(format, badgeData);
+      sendBadge(format, badgeData)
+    } catch (e) {
+      badgeData.text[1] = 'invalid'
+      sendBadge(format, badgeData)
     }
-  });
+  })
 }
 
 module.exports = {
-  teamcityBadge
-};
+  teamcityBadge,
+}
diff --git a/lib/test-config.js b/lib/test-config.js
index 2daaed0643fb86e071f9d068bd170f3c95ea9c24..50206d4a629f5421b6f372cde1b40563e1c6695a 100644
--- a/lib/test-config.js
+++ b/lib/test-config.js
@@ -1,5 +1,5 @@
-'use strict';
+'use strict'
 
 module.exports = {
-  port: 1111
-};
+  port: 1111,
+}
diff --git a/lib/text-formatters.js b/lib/text-formatters.js
index fa42a93f4cccd53c6260b9bd0ba6b5102b0934ac..e38f71bf918d9c975fee9721086f6f773be77af8 100644
--- a/lib/text-formatters.js
+++ b/lib/text-formatters.js
@@ -2,100 +2,113 @@
  * Commonly-used functions for formatting text in badge labels. Includes
  * ordinal numbers, currency codes, star ratings, versions, etc.
  */
-'use strict';
+'use strict'
 
-const moment = require('moment');
-moment().format();
+const moment = require('moment')
+moment().format()
 
 function starRating(rating) {
-  const flooredRating =  Math.floor(rating);
-  let stars = '';
-  while (stars.length < flooredRating) { stars += '★'; }
-  const decimal = rating - flooredRating;
-  if (decimal >= 0.875) { stars += '★'; }
-  else if (decimal >= 0.625) { stars += '¾'; }
-  else if (decimal >= 0.375) { stars += '½'; }
-  else if (decimal >= 0.125) { stars += '¼'; }
-  while (stars.length < 5) { stars += '☆'; }
-  return stars;
+  const flooredRating = Math.floor(rating)
+  let stars = ''
+  while (stars.length < flooredRating) {
+    stars += '★'
+  }
+  const decimal = rating - flooredRating
+  if (decimal >= 0.875) {
+    stars += '★'
+  } else if (decimal >= 0.625) {
+    stars += '¾'
+  } else if (decimal >= 0.375) {
+    stars += '½'
+  } else if (decimal >= 0.125) {
+    stars += '¼'
+  }
+  while (stars.length < 5) {
+    stars += '☆'
+  }
+  return stars
 }
 
 // Convert ISO 4217 code to unicode string.
 function currencyFromCode(code) {
-  return ({
-    CNY: '¥',
-    EUR: '€',
-    GBP: '₤',
-    USD: '$',
-  })[code] || code;
+  return (
+    {
+      CNY: '¥',
+      EUR: '€',
+      GBP: '₤',
+      USD: '$',
+    }[code] || code
+  )
 }
 
 function ordinalNumber(n) {
-  const s=['ᵗʰ','ˢᵗ','ⁿᵈ','ʳᵈ'], v=n%100;
-  return n+(s[(v-20)%10]||s[v]||s[0]);
+  const s = ['ᵗʰ', 'ˢᵗ', 'ⁿᵈ', 'ʳᵈ'],
+    v = n % 100
+  return n + (s[(v - 20) % 10] || s[v] || s[0])
 }
 
 // Given a number, string with appropriate unit in the metric system, SI.
 // Note: numbers beyond the peta- cannot be represented as integers in JS.
-const metricPrefix = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
-const metricPower = metricPrefix
-    .map(function(a, i) { return Math.pow(1000, i + 1); });
+const metricPrefix = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
+const metricPower = metricPrefix.map(function(a, i) {
+  return Math.pow(1000, i + 1)
+})
 function metric(n) {
   for (let i = metricPrefix.length - 1; i >= 0; i--) {
-    const limit = metricPower[i];
+    const limit = metricPower[i]
     if (n >= limit) {
-      n = Math.round(n / limit);
+      n = Math.round(n / limit)
       if (n < 1000) {
-        return '' + n + metricPrefix[i];
+        return '' + n + metricPrefix[i]
       } else {
-        return '1' + metricPrefix[i + 1];
+        return '1' + metricPrefix[i + 1]
       }
     }
   }
-  return '' + n;
+  return '' + n
 }
 
 // Remove the starting v in a string.
 function omitv(version) {
   if (version.charCodeAt(0) === 118) {
-    return version.slice(1);
+    return version.slice(1)
   }
-  return version;
+  return version
 }
 
 // Add a starting v to the version unless:
 // - it does not start with a digit
 // - it is a date (yyyy-mm-dd)
-const ignoredVersionPatterns = /^[^0-9]|[0-9]{4}-[0-9]{2}-[0-9]{2}/;
+const ignoredVersionPatterns = /^[^0-9]|[0-9]{4}-[0-9]{2}-[0-9]{2}/
 function addv(version) {
-  version = '' + version;
+  version = '' + version
   if (version.startsWith('v') || ignoredVersionPatterns.test(version)) {
-    return version;
+    return version
   } else {
-    return `v${version}`;
+    return `v${version}`
   }
 }
 
 function maybePluralize(singular, countable, plural) {
-  plural = plural || `${singular}s`;
+  plural = plural || `${singular}s`
 
   if (countable && countable.length === 1) {
-    return singular;
+    return singular
   } else {
-    return plural;
+    return plural
   }
 }
 
 function formatDate(d) {
-  const date = moment(d);
+  const date = moment(d)
   const dateString = date.calendar(null, {
     lastDay: '[yesterday]',
     sameDay: '[today]',
     lastWeek: '[last] dddd',
-    sameElse: 'MMMM YYYY'
-  });
+    sameElse: 'MMMM YYYY',
+  })
   // Trim current year from date string
-  return dateString.replace(` ${moment().year()}`, '').toLowerCase();
+  return dateString.replace(` ${moment().year()}`, '').toLowerCase()
 }
 
 module.exports = {
@@ -106,5 +119,5 @@ module.exports = {
   omitv,
   addv,
   maybePluralize,
-  formatDate
-};
+  formatDate,
+}
diff --git a/lib/text-formatters.spec.js b/lib/text-formatters.spec.js
index 0a5d4d7ba36a0d5819b51456f2bdcdfb07889063..a4885dd658919d53f3d96ca950fe805ac7070c9c 100644
--- a/lib/text-formatters.spec.js
+++ b/lib/text-formatters.spec.js
@@ -1,7 +1,7 @@
-'use strict';
+'use strict'
 
-const { test, given } = require('sazerac');
-const sinon = require('sinon');
+const { test, given } = require('sazerac')
+const sinon = require('sinon')
 const {
   starRating,
   currencyFromCode,
@@ -10,83 +10,87 @@ const {
   omitv,
   addv,
   maybePluralize,
-  formatDate
-} = require('./text-formatters');
+  formatDate,
+} = require('./text-formatters')
 
 describe('Text formatters', function() {
   test(starRating, () => {
-    given(4.9).expect('★★★★★');
-    given(3.7).expect('★★★¾☆');
-    given(2.566).expect('★★½☆☆');
-    given(2.2).expect('★★¼☆☆');
-    given(3).expect('★★★☆☆');
-  });
+    given(4.9).expect('★★★★★')
+    given(3.7).expect('★★★¾☆')
+    given(2.566).expect('★★½☆☆')
+    given(2.2).expect('★★¼☆☆')
+    given(3).expect('★★★☆☆')
+  })
 
   test(currencyFromCode, () => {
-    given('CNY').expect('¥');
-    given('EUR').expect('€');
-    given('GBP').expect('₤');
-    given('USD').expect('$');
-    given('AUD').expect('AUD');
-  });
+    given('CNY').expect('¥')
+    given('EUR').expect('€')
+    given('GBP').expect('₤')
+    given('USD').expect('$')
+    given('AUD').expect('AUD')
+  })
 
   test(ordinalNumber, () => {
-    given(2).expect('2ⁿᵈ');
-    given(11).expect('11ᵗʰ');
-    given(23).expect('23ʳᵈ');
-    given(131).expect('131ˢᵗ');
-  });
+    given(2).expect('2ⁿᵈ')
+    given(11).expect('11ᵗʰ')
+    given(23).expect('23ʳᵈ')
+    given(131).expect('131ˢᵗ')
+  })
 
   test(metric, () => {
-    given(999).expect('999');
-    given(1000).expect('1k');
-    given(999499).expect('999k');
-    given(999500).expect('1M');
-    given(1578896212).expect('2G');
-    given(80000000000000).expect('80T');
-    given(4000000000000001).expect('4P');
-    given(71007000100580002000).expect('71E');
-    given(1000000000000000000000).expect('1Z');
-    given(2222222222222222222222222).expect('2Y');
-  });
+    given(999).expect('999')
+    given(1000).expect('1k')
+    given(999499).expect('999k')
+    given(999500).expect('1M')
+    given(1578896212).expect('2G')
+    given(80000000000000).expect('80T')
+    given(4000000000000001).expect('4P')
+    given(71007000100580002000).expect('71E')
+    given(1000000000000000000000).expect('1Z')
+    given(2222222222222222222222222).expect('2Y')
+  })
 
   test(omitv, () => {
-    given('hello').expect('hello');
-    given('v1.0.1').expect('1.0.1');
-  });
+    given('hello').expect('hello')
+    given('v1.0.1').expect('1.0.1')
+  })
 
   test(addv, () => {
-    given(9).expect('v9');
-    given(0.1).expect('v0.1');
-    given('1.0.0').expect('v1.0.0');
-    given('v0.6').expect('v0.6');
-    given('hello').expect('hello');
-    given('2017-05-05-Release-2.3.17').expect('2017-05-05-Release-2.3.17');
-  });
+    given(9).expect('v9')
+    given(0.1).expect('v0.1')
+    given('1.0.0').expect('v1.0.0')
+    given('v0.6').expect('v0.6')
+    given('hello').expect('hello')
+    given('2017-05-05-Release-2.3.17').expect('2017-05-05-Release-2.3.17')
+  })
 
   test(maybePluralize, () => {
-    given('foo', []).expect('foos');
-    given('foo', [123]).expect('foo');
-    given('foo', [123, 456]).expect('foos');
-    given('foo', undefined).expect('foos');
+    given('foo', []).expect('foos')
+    given('foo', [123]).expect('foo')
+    given('foo', [123, 456]).expect('foos')
+    given('foo', undefined).expect('foos')
 
-    given('box', [], 'boxes').expect('boxes');
-    given('box', [123], 'boxes').expect('box');
-    given('box', [123, 456], 'boxes').expect('boxes');
-    given('box', undefined, 'boxes').expect('boxes');
-  });
+    given('box', [], 'boxes').expect('boxes')
+    given('box', [123], 'boxes').expect('box')
+    given('box', [123, 456], 'boxes').expect('boxes')
+    given('box', undefined, 'boxes').expect('boxes')
+  })
 
   test(formatDate, () => {
-    given(1465513200000).describe('when given a timestamp in june 2016').expect('june 2016');
-  });
+    given(1465513200000)
+      .describe('when given a timestamp in june 2016')
+      .expect('june 2016')
+  })
 
-  context('in october', function () {
-    beforeEach(function () {
-      sinon.useFakeTimers(new Date(2017, 9, 15).getTime());
-    });
+  context('in october', function() {
+    beforeEach(function() {
+      sinon.useFakeTimers(new Date(2017, 9, 15).getTime())
+    })
 
     test(formatDate, () => {
-      given(new Date(2017, 0, 1).getTime()).describe('when given the beginning of this year').expect('january');
-    });
-  });
-});
+      given(new Date(2017, 0, 1).getTime())
+        .describe('when given the beginning of this year')
+        .expect('january')
+    })
+  })
+})
diff --git a/lib/text-measurer.js b/lib/text-measurer.js
index 916ddeba8538f27d411fd4a0a40894e494401f7e..dae729a6a581c434495de4bf5effb6c3faf7da99 100644
--- a/lib/text-measurer.js
+++ b/lib/text-measurer.js
@@ -1,26 +1,30 @@
-'use strict';
+'use strict'
 
-const PDFDocument = require('pdfkit');
+const PDFDocument = require('pdfkit')
 
 class PDFKitTextMeasurer {
   constructor(fontPath, fallbackFontPath) {
-    this.document = new PDFDocument({ size: 'A4', layout: 'landscape' })
-      .fontSize(11);
+    this.document = new PDFDocument({
+      size: 'A4',
+      layout: 'landscape',
+    }).fontSize(11)
     try {
-      this.document.font(fontPath);
-    } catch(e) {
+      this.document.font(fontPath)
+    } catch (e) {
       if (fallbackFontPath) {
-        console.error(`Text-width computation may be incorrect. Unable to load font at ${fontPath}. Using fallback font ${fallbackFontPath} instead.`);
-        this.document.font(fallbackFontPath);
+        console.error(
+          `Text-width computation may be incorrect. Unable to load font at ${fontPath}. Using fallback font ${fallbackFontPath} instead.`
+        )
+        this.document.font(fallbackFontPath)
       } else {
-        console.error('No fallback font set.');
-        throw e;
+        console.error('No fallback font set.')
+        throw e
       }
     }
   }
 
   widthOf(str) {
-    return this.document.widthOfString(str);
+    return this.document.widthOfString(str)
   }
 }
 
@@ -29,61 +33,62 @@ class QuickTextMeasurer {
     this.baseMeasurer = new PDFKitTextMeasurer(fontPath, fallbackFontPath)
 
     // This will be a Map of characters -> numbers.
-    this.characterWidths = new Map();
+    this.characterWidths = new Map()
     // This will be Map of Maps of characters -> numbers.
-    this.kerningPairs = new Map();
-    this._prepare();
+    this.kerningPairs = new Map()
+    this._prepare()
   }
 
   static printableAsciiCharacters() {
-    const printableRange = [32, 126];
-    const length = printableRange[1] - printableRange[0] + 1;
-    return Array
-      .from({ length }, (value, i) => printableRange[0] + i)
-      .map(charCode => String.fromCharCode(charCode));
+    const printableRange = [32, 126]
+    const length = printableRange[1] - printableRange[0] + 1
+    return Array.from({ length }, (value, i) => printableRange[0] + i).map(
+      charCode => String.fromCharCode(charCode)
+    )
   }
 
   _prepare() {
-    const charactersToCache = this.constructor.printableAsciiCharacters();
+    const charactersToCache = this.constructor.printableAsciiCharacters()
 
     charactersToCache.forEach(char => {
-      this.characterWidths.set(char, this.baseMeasurer.widthOf(char));
-      this.kerningPairs.set(char, new Map());
-    });
+      this.characterWidths.set(char, this.baseMeasurer.widthOf(char))
+      this.kerningPairs.set(char, new Map())
+    })
 
     charactersToCache.forEach(first => {
       charactersToCache.forEach(second => {
-        const individually = this.characterWidths.get(first) + this.characterWidths.get(second);
-        const asPair = this.baseMeasurer.widthOf(`${first}${second}`);
-        const kerningAdjustment = asPair - individually;
-        this.kerningPairs.get(first).set(second, kerningAdjustment);
-      });
-    });
+        const individually =
+          this.characterWidths.get(first) + this.characterWidths.get(second)
+        const asPair = this.baseMeasurer.widthOf(`${first}${second}`)
+        const kerningAdjustment = asPair - individually
+        this.kerningPairs.get(first).set(second, kerningAdjustment)
+      })
+    })
   }
 
   widthOf(str) {
-    const { characterWidths, kerningPairs } = this;
+    const { characterWidths, kerningPairs } = this
 
-    let result = 0;
-    let previous = null;
+    let result = 0
+    let previous = null
     for (const character of str) {
       if (!characterWidths.has(character)) {
         // Bail.
-        return this.baseMeasurer.widthOf(str);
+        return this.baseMeasurer.widthOf(str)
       }
 
-      result += characterWidths.get(character);
+      result += characterWidths.get(character)
       if (previous !== null) {
-        result += kerningPairs.get(previous).get(character);
+        result += kerningPairs.get(previous).get(character)
       }
 
-      previous = character;
+      previous = character
     }
-    return result;
+    return result
   }
 }
 
 module.exports = {
   PDFKitTextMeasurer,
   QuickTextMeasurer,
-};
+}
diff --git a/lib/text-measurer.spec.js b/lib/text-measurer.spec.js
index 6f944ea0603279ebdb1664acafbdf8a50b374680..1ea58ea22868abc977090eeddca2756e7685a61c 100644
--- a/lib/text-measurer.spec.js
+++ b/lib/text-measurer.spec.js
@@ -1,142 +1,154 @@
-'use strict';
-
-const { expect } = require('chai');
-const path = require('path');
-const fs = require('fs');
-const sinon = require('sinon');
-const { PDFKitTextMeasurer, QuickTextMeasurer } = require('./text-measurer');
-const { starRating } = require('./text-formatters');
-const defaults = require('./defaults');
-const testHelpers = require('./make-badge-test-helpers');
-const almostEqual = require('almost-equal');
-
-const EPSILON_PIXELS = 1e-3;
-
-describe('PDFKitTextMeasurer with DejaVu Sans', function () {
-  it('should produce the same length as before', function () {
-    const measurer = new PDFKitTextMeasurer(testHelpers.font.path);
-    expect(measurer.widthOf('This is the dawning of the Age of Aquariums'))
-      .to.equal(243.546875);
-  });
-});
+'use strict'
+
+const { expect } = require('chai')
+const path = require('path')
+const fs = require('fs')
+const sinon = require('sinon')
+const { PDFKitTextMeasurer, QuickTextMeasurer } = require('./text-measurer')
+const { starRating } = require('./text-formatters')
+const defaults = require('./defaults')
+const testHelpers = require('./make-badge-test-helpers')
+const almostEqual = require('almost-equal')
+
+const EPSILON_PIXELS = 1e-3
+
+describe('PDFKitTextMeasurer with DejaVu Sans', function() {
+  it('should produce the same length as before', function() {
+    const measurer = new PDFKitTextMeasurer(testHelpers.font.path)
+    expect(
+      measurer.widthOf('This is the dawning of the Age of Aquariums')
+    ).to.equal(243.546875)
+  })
+})
 
 function registerTests(fontPath, skip) {
   // Invoke `.skip()` within the `it`'s so we get logging of the skipped tests.
-  const displayName = path.basename(fontPath, path.extname(fontPath));
+  const displayName = path.basename(fontPath, path.extname(fontPath))
 
-  describe(`QuickTextMeasurer with ${displayName}`, function () {
-    let quickMeasurer;
-    if (! skip) {
-      before(function () {
+  describe(`QuickTextMeasurer with ${displayName}`, function() {
+    let quickMeasurer
+    if (!skip) {
+      before(function() {
         // Since this is slow, share it across all tests.
-        quickMeasurer = new QuickTextMeasurer(fontPath);
-      });
+        quickMeasurer = new QuickTextMeasurer(fontPath)
+      })
     }
 
-    let sandbox;
-    let pdfKitWidthOf;
-    let pdfKitMeasurer;
-    if (! skip) {
+    let sandbox
+    let pdfKitWidthOf
+    let pdfKitMeasurer
+    if (!skip) {
       // Boo, the sandbox doesn't get cleaned up after a skipped test.
-      beforeEach(function () {
+      beforeEach(function() {
         // This often times out: https://circleci.com/gh/badges/shields/2786
-        this.timeout(5000);
-        sandbox = sinon.createSandbox();
-        pdfKitWidthOf = sandbox.spy(PDFKitTextMeasurer.prototype, 'widthOf');
-        pdfKitMeasurer = new PDFKitTextMeasurer(fontPath);
-      });
+        this.timeout(5000)
+        sandbox = sinon.createSandbox()
+        pdfKitWidthOf = sandbox.spy(PDFKitTextMeasurer.prototype, 'widthOf')
+        pdfKitMeasurer = new PDFKitTextMeasurer(fontPath)
+      })
 
-      afterEach(function () {
+      afterEach(function() {
         if (sandbox) {
-          sandbox.restore();
-          sandbox = null;
+          sandbox.restore()
+          sandbox = null
         }
-      });
+      })
     }
 
-    context('when given ASCII strings', function () {
+    context('when given ASCII strings', function() {
       const strings = [
         'This is the dawning of the Age of Aquariums',
         'v1.2.511',
         '5 passed, 2 failed, 1 skipped',
         '[prismic "1.1"]',
-      ];
-
-      strings.forEach(function (str) {
-        it(`should measure '${str}' in parity with PDFKit`, function () {
-          if (skip) { this.skip(); }
-          expect(quickMeasurer.widthOf(str))
-            .to.be.closeTo(pdfKitMeasurer.widthOf(str), EPSILON_PIXELS);
-        });
-      });
-
-      strings.forEach(function (str) {
-        it(`should measure '${str}' without invoking PDFKit`, function () {
-          if (skip) { this.skip(); }
-          quickMeasurer.widthOf(str);
-          expect(pdfKitWidthOf).not.to.have.been.called;
-        });
-      });
-
-      context('when the font includes a kerning pair', function () {
+      ]
+
+      strings.forEach(function(str) {
+        it(`should measure '${str}' in parity with PDFKit`, function() {
+          if (skip) {
+            this.skip()
+          }
+          expect(quickMeasurer.widthOf(str)).to.be.closeTo(
+            pdfKitMeasurer.widthOf(str),
+            EPSILON_PIXELS
+          )
+        })
+      })
+
+      strings.forEach(function(str) {
+        it(`should measure '${str}' without invoking PDFKit`, function() {
+          if (skip) {
+            this.skip()
+          }
+          quickMeasurer.widthOf(str)
+          expect(pdfKitWidthOf).not.to.have.been.called
+        })
+      })
+
+      context('when the font includes a kerning pair', function() {
         const stringsWithKerningPairs = [
           'Q-tips', // In DejaVu, Q- is a kerning pair.
           'B-flat', // In Verdana, B- is a kerning pair.
-        ];
+        ]
 
         function widthByMeasuringCharacters(str) {
-          let result = 0;
+          let result = 0
           for (const char of str) {
-            result += pdfKitMeasurer.widthOf(char);
+            result += pdfKitMeasurer.widthOf(char)
           }
-          return result;
+          return result
         }
 
-        it(`should apply a width correction`, function () {
-          if (skip) { this.skip(); }
+        it(`should apply a width correction`, function() {
+          if (skip) {
+            this.skip()
+          }
 
-          const adjustedStrings = [];
+          const adjustedStrings = []
 
           stringsWithKerningPairs.forEach(str => {
-            const actual = quickMeasurer.widthOf(str);
-            const unadjusted = widthByMeasuringCharacters(str);
+            const actual = quickMeasurer.widthOf(str)
+            const unadjusted = widthByMeasuringCharacters(str)
             if (!almostEqual(actual, unadjusted, EPSILON_PIXELS)) {
-              adjustedStrings.push(str);
+              adjustedStrings.push(str)
             }
-          });
+          })
 
-          expect(adjustedStrings).to.be.an('array').that.is.not.empty;
-        });
-      });
-    });
+          expect(adjustedStrings).to.be.an('array').that.is.not.empty
+        })
+      })
+    })
 
-    context('when given non-ASCII strings', function () {
-      const strings = [
-        starRating(3.5),
-        '\u2026',
-      ];
-
-      strings.forEach(function (str) {
-        it(`should measure '${str}' in parity with PDFKit`, function () {
-          if (skip) { this.skip(); }
-          expect(quickMeasurer.widthOf(str))
-            .to.be.closeTo(pdfKitMeasurer.widthOf(str), EPSILON_PIXELS);
-        });
-      });
-
-      strings.forEach(function (str) {
-        it(`should invoke the base when measuring '${str}'`, function () {
-          if (skip) { this.skip(); }
-          quickMeasurer.widthOf(str);
-          expect(pdfKitWidthOf).to.have.been.called;
-        });
-      });
-    });
-  });
-};
+    context('when given non-ASCII strings', function() {
+      const strings = [starRating(3.5), '\u2026']
+
+      strings.forEach(function(str) {
+        it(`should measure '${str}' in parity with PDFKit`, function() {
+          if (skip) {
+            this.skip()
+          }
+          expect(quickMeasurer.widthOf(str)).to.be.closeTo(
+            pdfKitMeasurer.widthOf(str),
+            EPSILON_PIXELS
+          )
+        })
+      })
+
+      strings.forEach(function(str) {
+        it(`should invoke the base when measuring '${str}'`, function() {
+          if (skip) {
+            this.skip()
+          }
+          quickMeasurer.widthOf(str)
+          expect(pdfKitWidthOf).to.have.been.called
+        })
+      })
+    })
+  })
+}
 
 // i.e. Verdana
-registerTests(defaults.font.path, !fs.existsSync(defaults.font.path));
+registerTests(defaults.font.path, !fs.existsSync(defaults.font.path))
 
 // i.e. DejaVu Sans
-registerTests(testHelpers.font.path);
+registerTests(testHelpers.font.path)
diff --git a/lib/token-pool.js b/lib/token-pool.js
index 8ce368efb4274ab16912dc751afbfb27f054ced9..cd22a6ec2c4ea09410821f9432a732506ffc7c25 100644
--- a/lib/token-pool.js
+++ b/lib/token-pool.js
@@ -1,13 +1,13 @@
-'use strict';
+'use strict'
 
-const PriorityQueue = require('priorityqueuejs');
+const PriorityQueue = require('priorityqueuejs')
 
 // Encapsulate a rate-limited token, with a user-provided ID and user-provided data.
 //
 // Each token has a notion of the number of uses remaining until exhausted,
 // and the next reset time, when it can be used again even if it's exhausted.
 class Token {
-  constructor (id, data, usesRemaining, nextReset) {
+  constructor(id, data, usesRemaining, nextReset) {
     // Use underscores to avoid conflict with property accessors.
     Object.assign(this, {
       _id: id,
@@ -16,73 +16,86 @@ class Token {
       _nextReset: nextReset,
       _isValid: true,
       _isFrozen: false,
-    });
+    })
   }
 
-  get id () { return this._id; }
-  get data () { return this._data; }
-  get usesRemaining () { return this._usesRemaining; }
-  get nextReset () { return this._nextReset; }
-  get isValid () { return this._isValid; }
+  get id() {
+    return this._id
+  }
+  get data() {
+    return this._data
+  }
+  get usesRemaining() {
+    return this._usesRemaining
+  }
+  get nextReset() {
+    return this._nextReset
+  }
+  get isValid() {
+    return this._isValid
+  }
 
-  static utcEpochSeconds () {
-    return Date.now() / 1000 >>> 0;
+  static utcEpochSeconds() {
+    return (Date.now() / 1000) >>> 0
   }
 
-  get hasReset () {
-    return this.constructor.utcEpochSeconds() >= this.nextReset;
+  get hasReset() {
+    return this.constructor.utcEpochSeconds() >= this.nextReset
   }
 
-  get isExhausted () {
-    return this.usesRemaining <= 0 && ! this.hasReset;
+  get isExhausted() {
+    return this.usesRemaining <= 0 && !this.hasReset
   }
 
   // Update the uses remaining and next reset time for a token.
-  update (usesRemaining, nextReset) {
-    if (! Number.isInteger(usesRemaining)) {
-      throw Error('usesRemaining must be an integer');
+  update(usesRemaining, nextReset) {
+    if (!Number.isInteger(usesRemaining)) {
+      throw Error('usesRemaining must be an integer')
     }
-    if (! Number.isInteger(nextReset)) {
-      throw Error('nextReset must be an integer');
+    if (!Number.isInteger(nextReset)) {
+      throw Error('nextReset must be an integer')
     }
 
     if (this._isFrozen) {
-      return;
+      return
     }
 
     // Since the token pool will typically return the same token for many uses
     // before moving on to another, `update()` may be called many times. Since
     // the sequence of responses may be indeterminate, keep the "worst case"
     // value for uses remaining.
-    if (this._nextReset === this.constructor.nextResetNever || nextReset > this._nextReset) {
-      this._nextReset = nextReset;
-      this._usesRemaining = usesRemaining;
+    if (
+      this._nextReset === this.constructor.nextResetNever ||
+      nextReset > this._nextReset
+    ) {
+      this._nextReset = nextReset
+      this._usesRemaining = usesRemaining
     } else if (nextReset === this._nextReset) {
-      this._usesRemaining = Math.min(this._usesRemaining, usesRemaining);
+      this._usesRemaining = Math.min(this._usesRemaining, usesRemaining)
     } else {
       // Discard the new update; it's older than the values we have.
     }
   }
 
   // Indicate that the token should no longer be used.
-  invalidate () {
-    this._isValid = false;
+  invalidate() {
+    this._isValid = false
   }
 
   // Freeze the uses remaining and next reset values. Helpful for keeping
   // stable ordering for a valid priority queue.
-  freeze () {
-    this._isFrozen = true;
+  freeze() {
+    this._isFrozen = true
   }
 
   // Unfreeze the uses remaining and next reset values.
-  unfreeze () {
-    this._isFrozen = false;
+  unfreeze() {
+    this._isFrozen = false
   }
 }
 
 // Large sentinel value which means "never reset".
-Token.nextResetNever = Number.MAX_SAFE_INTEGER;
+Token.nextResetNever = Number.MAX_SAFE_INTEGER
 
 // Encapsulate a collection of rate-limited tokens and choose the next
 // available token when one is needed.
@@ -92,22 +105,22 @@ Token.nextResetNever = Number.MAX_SAFE_INTEGER;
 class TokenPool {
   // batchSize: The maximum number of times we use each token before moving
   //   on to the next one.
-  constructor (batchSize) {
-    this.batchSize = batchSize;
+  constructor(batchSize) {
+    this.batchSize = batchSize
 
-    this.currentBatch = { currentToken: null, remaining: 0 };
+    this.currentBatch = { currentToken: null, remaining: 0 }
 
     // A set of IDs used for deduplication.
-    this.tokenIds = new Set();
+    this.tokenIds = new Set()
 
     // See discussion on the FIFO and priority queues in `next()`.
-    this.fifoQueue = [];
-    this.priorityQueue = new PriorityQueue(this.constructor.compareTokens);
+    this.fifoQueue = []
+    this.priorityQueue = new PriorityQueue(this.constructor.compareTokens)
   }
 
   // Use the token whose current rate allotment is expiring soonest.
-  static compareTokens (first, second) {
-    return second.nextReset - first.nextReset;
+  static compareTokens(first, second) {
+    return second.nextReset - first.nextReset
   }
 
   // Add a token with user-provided ID and data.
@@ -115,54 +128,54 @@ class TokenPool {
   // The ID can be a primitive value or an object reference, and is used (with
   // `Set`) for deduplication. If a token already exists with a given id, it
   // will be ignored.
-  add (id, data, usesRemaining, nextReset) {
+  add(id, data, usesRemaining, nextReset) {
     if (this.tokenIds.has(id)) {
-      return false;
+      return false
     }
-    this.tokenIds.add(id);
+    this.tokenIds.add(id)
 
-    usesRemaining = usesRemaining === undefined ? this.batchSize : usesRemaining;
-    nextReset = nextReset === undefined ? Token.nextResetNever : nextReset;
+    usesRemaining = usesRemaining === undefined ? this.batchSize : usesRemaining
+    nextReset = nextReset === undefined ? Token.nextResetNever : nextReset
 
-    const token = new Token(id, data, usesRemaining, nextReset);
-    this.fifoQueue.push(token);
+    const token = new Token(id, data, usesRemaining, nextReset)
+    this.fifoQueue.push(token)
 
-    return true;
+    return true
   }
 
   // Prepare to start a new batch by obtaining and returning the next usable
   // token.
-  _nextBatch () {
-    let next;
+  _nextBatch() {
+    let next
 
     while ((next = this.fifoQueue.shift())) {
-      if (! next.isValid) {
+      if (!next.isValid) {
         // Discard, and
-        continue;
+        continue
       } else if (next.isExhausted) {
-        next.freeze();
-        this.priorityQueue.enq(next);
+        next.freeze()
+        this.priorityQueue.enq(next)
       } else {
-        return next;
+        return next
       }
     }
 
     while ((next = this.priorityQueue.peek())) {
-      if (! next.isValid) {
+      if (!next.isValid) {
         // Discard, and
-        continue;
+        continue
       } else if (next.isExhausted) {
         // No need to check any more tokens, since they all reset after this
         // one.
-        break;
+        break
       } else {
-        this.priorityQueue.deq(); // deq next
-        next.unfreeze();
-        return next;
+        this.priorityQueue.deq() // deq next
+        next.unfreeze()
+        return next
       }
     }
 
-    throw Error('Token pool is exhausted');
+    throw Error('Token pool is exhausted')
   }
 
   // Obtain the next available token, returning `null` if no tokens are
@@ -190,38 +203,40 @@ class TokenPool {
   // After obtaining a token using `next()`, invoke `update()` on it to set a
   // new use-remaining count and next-reset time. Invoke `invalidate()` to
   // indicate it should not be reused.
-  next () {
-    let token = this.currentBatch.token;
-    const remaining = this.currentBatch.remaining;
+  next() {
+    let token = this.currentBatch.token
+    const remaining = this.currentBatch.remaining
 
-    if (remaining <= 0 || ! token.isValid || token.isExhausted) {
-      token = this._nextBatch();
+    if (remaining <= 0 || !token.isValid || token.isExhausted) {
+      token = this._nextBatch()
       this.currentBatch = {
         token,
-        remaining: token.hasReset ? this.batchSize : Math.min(this.batchSize, token.usesRemaining),
-      };
-      this.fifoQueue.push(token);
+        remaining: token.hasReset
+          ? this.batchSize
+          : Math.min(this.batchSize, token.usesRemaining),
+      }
+      this.fifoQueue.push(token)
     }
 
-    this.currentBatch.remaining -= 1;
+    this.currentBatch.remaining -= 1
 
-    return token;
+    return token
   }
 
   // Iterate over all valid tokens.
-  forEach (callback) {
-    function visit (item) {
+  forEach(callback) {
+    function visit(item) {
       if (item.isValid) {
-        callback(item);
-      };
+        callback(item)
+      }
     }
 
-    this.fifoQueue.forEach(visit);
-    this.priorityQueue.forEach(visit);
+    this.fifoQueue.forEach(visit)
+    this.priorityQueue.forEach(visit)
   }
 }
 
 module.exports = {
   Token,
   TokenPool,
-};
+}
diff --git a/lib/token-pool.spec.js b/lib/token-pool.spec.js
index c5d9c07709ca863c610e26b17a42163cf06569c9..9a2df2d9ca60c023aeb9cec86d9d9010f8589279 100644
--- a/lib/token-pool.spec.js
+++ b/lib/token-pool.spec.js
@@ -1,107 +1,121 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const sinon = require('sinon');
-const times = require('lodash.times');
-const { Token, TokenPool } = require('./token-pool');
+const { expect } = require('chai')
+const sinon = require('sinon')
+const times = require('lodash.times')
+const { Token, TokenPool } = require('./token-pool')
 
-function expectPoolToBeExhausted (pool) {
+function expectPoolToBeExhausted(pool) {
   expect(() => {
-    pool.next();
-  }).to.throw(Error, /^Token pool is exhausted$/);
+    pool.next()
+  }).to.throw(Error, /^Token pool is exhausted$/)
 }
 
-describe('The token pool', function () {
-  const ids = [1, 2, 3, 4, 5];
-  const batchSize = 3;
+describe('The token pool', function() {
+  const ids = [1, 2, 3, 4, 5]
+  const batchSize = 3
 
-  let tokenPool;
-  beforeEach(function () {
+  let tokenPool
+  beforeEach(function() {
     // Set up.
-    tokenPool = new TokenPool(batchSize);
-    ids.forEach(id => tokenPool.add(id));
-  });
-
-  it('should yield the expected tokens', function () {
-    ids.forEach(id => times(batchSize, () => expect(tokenPool.next().id).to.equal(id)));
-  });
-
-  it('should repeat when reaching the end', function () {
-    ids.forEach(id => times(batchSize, () => expect(tokenPool.next().id).to.equal(id)));
-    ids.forEach(id => times(batchSize, () => expect(tokenPool.next().id).to.equal(id)));
-  });
-
-  context('tokens are marked exhausted immediately', function () {
-    it('should be exhausted', function () {
+    tokenPool = new TokenPool(batchSize)
+    ids.forEach(id => tokenPool.add(id))
+  })
+
+  it('should yield the expected tokens', function() {
+    ids.forEach(id =>
+      times(batchSize, () => expect(tokenPool.next().id).to.equal(id))
+    )
+  })
+
+  it('should repeat when reaching the end', function() {
+    ids.forEach(id =>
+      times(batchSize, () => expect(tokenPool.next().id).to.equal(id))
+    )
+    ids.forEach(id =>
+      times(batchSize, () => expect(tokenPool.next().id).to.equal(id))
+    )
+  })
+
+  context('tokens are marked exhausted immediately', function() {
+    it('should be exhausted', function() {
       ids.forEach(() => {
-        const token = tokenPool.next();
-        token.update(0, Token.nextResetNever);
-      });
+        const token = tokenPool.next()
+        token.update(0, Token.nextResetNever)
+      })
 
-      expectPoolToBeExhausted(tokenPool);
-    });
-  });
+      expectPoolToBeExhausted(tokenPool)
+    })
+  })
 
-  context('tokens are marked after the last request', function () {
-    it('should be exhausted', function () {
+  context('tokens are marked after the last request', function() {
+    it('should be exhausted', function() {
       ids.forEach(() => {
-        const token = times(batchSize, () => tokenPool.next()).pop();
-        token.update(0, Token.nextResetNever);
-      });
+        const token = times(batchSize, () => tokenPool.next()).pop()
+        token.update(0, Token.nextResetNever)
+      })
 
-      expectPoolToBeExhausted(tokenPool);
-    });
-  });
+      expectPoolToBeExhausted(tokenPool)
+    })
+  })
 
-  context('tokens are renewed', function () {
-    it('should keep using them', function () {
-      const tokensToRenew = [2, 4];
-      const renewalCount = 3;
+  context('tokens are renewed', function() {
+    it('should keep using them', function() {
+      const tokensToRenew = [2, 4]
+      const renewalCount = 3
 
       ids.forEach(id => {
-        const token = times(batchSize, () => tokenPool.next()).pop();
-        const usesRemaining = tokensToRenew.includes(token.id) ? renewalCount : 0;
-        token.update(usesRemaining, Token.nextResetNever);
-      });
+        const token = times(batchSize, () => tokenPool.next()).pop()
+        const usesRemaining = tokensToRenew.includes(token.id)
+          ? renewalCount
+          : 0
+        token.update(usesRemaining, Token.nextResetNever)
+      })
 
       tokensToRenew.forEach(id => {
-        let token;
+        let token
         times(renewalCount, () => {
-          token = tokenPool.next();
-          expect(token.id).to.equal(id);
-        }).pop();
-        token.update(0, Token.nextResetNever);
-      });
-
-      expectPoolToBeExhausted(tokenPool);
-    });
-  });
-
-  context('tokens reset', function () {
-    let clock;
-    beforeEach(function () { clock = sinon.useFakeTimers(); });
-    afterEach(function () { clock.restore(); });
-
-    it('should start using them', function () {
-      const tokensToReset = [2, 4];
-      const futureTime = 1440;
+          token = tokenPool.next()
+          expect(token.id).to.equal(id)
+        }).pop()
+        token.update(0, Token.nextResetNever)
+      })
+
+      expectPoolToBeExhausted(tokenPool)
+    })
+  })
+
+  context('tokens reset', function() {
+    let clock
+    beforeEach(function() {
+      clock = sinon.useFakeTimers()
+    })
+    afterEach(function() {
+      clock.restore()
+    })
+
+    it('should start using them', function() {
+      const tokensToReset = [2, 4]
+      const futureTime = 1440
 
       ids.forEach(id => {
-        const token = times(batchSize, () => tokenPool.next()).pop();
-        const nextReset = tokensToReset.includes(token.id) ? futureTime : Token.nextResetNever;
-        token.update(0, nextReset);
-      });
+        const token = times(batchSize, () => tokenPool.next()).pop()
+        const nextReset = tokensToReset.includes(token.id)
+          ? futureTime
+          : Token.nextResetNever
+        token.update(0, nextReset)
+      })
 
-      expectPoolToBeExhausted(tokenPool);
+      expectPoolToBeExhausted(tokenPool)
 
-      clock.tick(1000 * futureTime);
+      clock.tick(1000 * futureTime)
 
       tokensToReset.forEach(id => {
-        const token = times(batchSize, () => tokenPool.next()).pop();
-        token.update(0, Token.nextResetNever);
-      });
-
-      expectPoolToBeExhausted(tokenPool);
-    });
-  });
-});
+        const token = times(batchSize, () => tokenPool.next()).pop()
+        token.update(0, Token.nextResetNever)
+      })
+
+      expectPoolToBeExhausted(tokenPool)
+    })
+  })
+})
diff --git a/lib/token-provider.js b/lib/token-provider.js
index c5dee6ff979799f0fcbe63e0b409e6e274464c73..46a06aa1cc44bb42ac1a1a1ac51aba3a6df2f429 100644
--- a/lib/token-provider.js
+++ b/lib/token-provider.js
@@ -1,28 +1,27 @@
-'use strict';
+'use strict'
 
-const {
-  Token,
-  TokenPool,
-} = require('./token-pool');
+const { Token, TokenPool } = require('./token-pool')
 
 class StaticTokenProvider {
-  constructor (tokenValidator, tokenString) {
+  constructor(tokenValidator, tokenString) {
     if (typeof tokenValidator !== 'function') {
-      throw Error('tokenValidator is not a function');
+      throw Error('tokenValidator is not a function')
     }
-    if (! tokenValidator(tokenString)) {
-      throw Error(`Not a valid token: ${tokenString}`);
+    if (!tokenValidator(tokenString)) {
+      throw Error(`Not a valid token: ${tokenString}`)
     }
 
-    this.staticToken = new Token(tokenString, null);
+    this.staticToken = new Token(tokenString, null)
   }
 
-  addToken () {
-    throw Error('When using token persistence, do not provide a static gh_token');
+  addToken() {
+    throw Error(
+      'When using token persistence, do not provide a static gh_token'
+    )
   }
 
-  nextToken () {
-    return this.staticToken;
+  nextToken() {
+    return this.staticToken
   }
 }
 
@@ -30,45 +29,45 @@ class PoolingTokenProvider {
   /*
   tokenValidator: A function which returns true if the argument is a valid token.
   */
-  constructor (tokenValidator) {
+  constructor(tokenValidator) {
     if (typeof tokenValidator !== 'function') {
-      throw Error('tokenValidator is not a function');
+      throw Error('tokenValidator is not a function')
     }
 
     Object.assign(this, {
       tokenValidator,
       batchSize: 25,
       searchBatchSize: 5,
-    });
+    })
 
-    this.tokenPool = new TokenPool(this.batchSize);
+    this.tokenPool = new TokenPool(this.batchSize)
   }
 
-  addToken (tokenString) {
-    if (! this.tokenValidator(tokenString)) {
-      throw Error(`Not a valid token: ${tokenString}`);
+  addToken(tokenString) {
+    if (!this.tokenValidator(tokenString)) {
+      throw Error(`Not a valid token: ${tokenString}`)
     }
 
-    this.tokenPool.add(tokenString, null, this.batchSize);
+    this.tokenPool.add(tokenString, null, this.batchSize)
   }
 
-  nextToken () {
-    return this.tokenPool.next();
+  nextToken() {
+    return this.tokenPool.next()
   }
 
   // Return an array of token strings.
-  toNative () {
-    const result = [];
+  toNative() {
+    const result = []
 
     this.tokenPool.forEach(token => {
-      result.push(token.id);
-    });
+      result.push(token.id)
+    })
 
-    return result;
+    return result
   }
 }
 
 module.exports = {
   StaticTokenProvider,
-  PoolingTokenProvider
-};
+  PoolingTokenProvider,
+}
diff --git a/lib/token-provider.spec.js b/lib/token-provider.spec.js
index 29f0d61f1081697270e01071c89d75c27ee5c2c1..606042667de87b569653598b352d9f7e87ad5f66 100644
--- a/lib/token-provider.spec.js
+++ b/lib/token-provider.spec.js
@@ -1,19 +1,19 @@
-'use strict';
+'use strict'
 
-const assert = require('assert');
-const { PoolingTokenProvider } = require('./token-provider');
+const assert = require('assert')
+const { PoolingTokenProvider } = require('./token-provider')
 const isValidGithubToken = require('./github-auth/is-valid-token')
 
-describe('The token provider', function () {
-  describe('toNative', function () {
-    it('should return the expected value', function () {
-      const tokens = ['1', '2', '3', '4', '5'].map(c => c.repeat(40));
-      const provider = new PoolingTokenProvider(isValidGithubToken);
-      tokens.forEach(t => provider.addToken(t));
+describe('The token provider', function() {
+  describe('toNative', function() {
+    it('should return the expected value', function() {
+      const tokens = ['1', '2', '3', '4', '5'].map(c => c.repeat(40))
+      const provider = new PoolingTokenProvider(isValidGithubToken)
+      tokens.forEach(t => provider.addToken(t))
       assert.deepStrictEqual(
         provider.toNative().sort(),
         Array.from(tokens).sort()
-      );
-    });
-  });
-});
+      )
+    })
+  })
+})
diff --git a/lib/unhandled-rejection.spec.js b/lib/unhandled-rejection.spec.js
index ec8b621c8934ee59b540c8c073f1ac2b9f609eaf..b155793b9b04f0caa45853cbc948e72efea41441 100644
--- a/lib/unhandled-rejection.spec.js
+++ b/lib/unhandled-rejection.spec.js
@@ -1,5 +1,7 @@
-'use strict';
+'use strict'
 
 // Cause unhandled promise rejections to fail unit tests, and print with stack
 // traces.
-process.on('unhandledRejection', error => { throw error; });
+process.on('unhandledRejection', error => {
+  throw error
+})
diff --git a/lib/version.js b/lib/version.js
index 1c83e068e13aeb05b8f3700bebe0324b65b80547..65f303b27f97792c6eceb72cadbe3fe7e0a13a67 100644
--- a/lib/version.js
+++ b/lib/version.js
@@ -5,56 +5,61 @@
  *
  * For utilities specific to PHP version ranges, see php-version.js.
  */
-'use strict';
+'use strict'
 
-const semver = require('semver');
+const semver = require('semver')
 
 // Given a list of versions (as strings), return the latest version.
 // Return undefined if no version could be found.
 function latest(versions, { pre = false } = {}) {
-  let version = '';
-  let origVersions = versions;
+  let version = ''
+  let origVersions = versions
   // return all results that are likely semver compatible versions
   versions = origVersions.filter(function(version) {
-    return (/\d+\.\d+/).test(version);
-  });
+    return /\d+\.\d+/.test(version)
+  })
   // If no semver versions then look for single numbered versions
-  if (!versions.length){
+  if (!versions.length) {
     versions = origVersions.filter(function(version) {
-      return (/\d+/).test(version);
-    });
+      return /\d+/.test(version)
+    })
   }
-  if (!pre){
+  if (!pre) {
     // remove pre-releases from array
     versions = versions.filter(function(version) {
-      return !(/\d+-\w+/).test(version);
-    });
+      return !/\d+-\w+/.test(version)
+    })
   }
   try {
     version = versions.sort((a, b) => {
       // coerce to string then lowercase otherwise alpha > RC
-      return semver.rcompare((''+a).toLowerCase(), (''+b).toLowerCase(), /* loose */ true);
-    })[0];
-  } catch(e) {
-    version = latestDottedVersion(versions);
+      return semver.rcompare(
+        ('' + a).toLowerCase(),
+        ('' + b).toLowerCase(),
+        /* loose */ true
+      )
+    })[0]
+  } catch (e) {
+    version = latestDottedVersion(versions)
   }
   if (version === undefined || version === null) {
-    origVersions = origVersions.sort();
-    version = origVersions[origVersions.length - 1];
+    origVersions = origVersions.sort()
+    version = origVersions[origVersions.length - 1]
   }
-  return version;
+  return version
 }
 
 function listCompare(a, b) {
-  const alen = a.length, blen = b.length;
+  const alen = a.length,
+    blen = b.length
   for (let i = 0; i < alen; i++) {
     if (a[i] < b[i]) {
-      return -1;
+      return -1
     } else if (a[i] > b[i]) {
-      return 1;
+      return 1
     }
   }
-  return alen - blen;
+  return alen - blen
 }
 
 // === Private helper functions ===
@@ -62,77 +67,86 @@ function listCompare(a, b) {
 // Take a list of string versions.
 // Return the latest, or undefined, if there are none.
 function latestDottedVersion(versions) {
-  const len = versions.length;
-  if (len === 0) { return; }
-  let version = versions[0];
+  const len = versions.length
+  if (len === 0) {
+    return
+  }
+  let version = versions[0]
   for (let i = 1; i < len; i++) {
     if (compareDottedVersion(version, versions[i]) < 0) {
-      version = versions[i];
+      version = versions[i]
     }
   }
-  return version;
+  return version
 }
 
 // Take string versions.
 // -1 if v1 < v2, 1 if v1 > v2, 0 otherwise.
 function compareDottedVersion(v1, v2) {
-  const parts1 = /([0-9.]+)(.*)$/.exec(v1);
-  const parts2 = /([0-9.]+)(.*)$/.exec(v2);
+  const parts1 = /([0-9.]+)(.*)$/.exec(v1)
+  const parts2 = /([0-9.]+)(.*)$/.exec(v2)
   if (parts1 != null && parts2 != null) {
-    const numbers1 = parts1[1];
-    const numbers2 = parts2[1];
-    const distinguisher1 = parts1[2];
-    const distinguisher2 = parts2[2];
-    const numlist1 = numbers1.split('.').map(function(e) { return +e; });
-    const numlist2 = numbers2.split('.').map(function(e) { return +e; });
-    const cmp = listCompare(numlist1, numlist2);
+    const numbers1 = parts1[1]
+    const numbers2 = parts2[1]
+    const distinguisher1 = parts1[2]
+    const distinguisher2 = parts2[2]
+    const numlist1 = numbers1.split('.').map(function(e) {
+      return +e
+    })
+    const numlist2 = numbers2.split('.').map(function(e) {
+      return +e
+    })
+    const cmp = listCompare(numlist1, numlist2)
     if (cmp !== 0) {
-      return cmp;
+      return cmp
     } else {
-      return distinguisher1 < distinguisher2? -1:
-        distinguisher1 > distinguisher2? 1: 0;
+      return distinguisher1 < distinguisher2
+        ? -1
+        : distinguisher1 > distinguisher2
+          ? 1
+          : 0
     }
   }
-  return v1 < v2? -1: v1 > v2? 1: 0;
+  return v1 < v2 ? -1 : v1 > v2 ? 1 : 0
 }
 
 // Slice the specified number of dotted parts from the given semver version.
 // e.g. slice('2.4.7', 'minor') -> '2.4'
 function slice(v, releaseType) {
-  if (! semver.valid(v, /* loose */ true)) {
-    return null;
+  if (!semver.valid(v, /* loose */ true)) {
+    return null
   }
 
-  const major = semver.major(v, /* loose */ true);
-  const minor = semver.minor(v, /* loose */ true);
-  const patch = semver.patch(v, /* loose */ true);
-  const prerelease = semver.prerelease(v, /* loose */ true);
+  const major = semver.major(v, /* loose */ true)
+  const minor = semver.minor(v, /* loose */ true)
+  const patch = semver.patch(v, /* loose */ true)
+  const prerelease = semver.prerelease(v, /* loose */ true)
 
   const dottedParts = {
     major: [major],
     minor: [major, minor],
     patch: [major, minor, patch],
-  }[releaseType];
+  }[releaseType]
 
   if (dottedParts === undefined) {
-    throw Error(`Unknown releaseType: ${releaseType}`);
+    throw Error(`Unknown releaseType: ${releaseType}`)
   }
 
-  const dotted = dottedParts.join('.');
+  const dotted = dottedParts.join('.')
   if (prerelease) {
-    return `${dotted}-${prerelease.join('.')}`;
+    return `${dotted}-${prerelease.join('.')}`
   } else {
-    return dotted;
+    return dotted
   }
 }
 
 function minor(v) {
-  return slice(v, 'minor');
+  return slice(v, 'minor')
 }
 
 function rangeStart(v) {
-  const range = new semver.Range(v, /* loose */ true);
-  return range.set[0][0].semver.version;
+  const range = new semver.Range(v, /* loose */ true)
+  return range.set[0][0].semver.version
 }
 
 module.exports = {
@@ -141,4 +155,4 @@ module.exports = {
   slice,
   minor,
   rangeStart,
-};
+}
diff --git a/lib/version.spec.js b/lib/version.spec.js
index 831a9852ab4533749b8123ebc07f657ce7956536..970714b89ed8dac856c7487fa8bd6937fb9eb518 100644
--- a/lib/version.spec.js
+++ b/lib/version.spec.js
@@ -1,67 +1,122 @@
-'use strict';
+'use strict'
 
-const { test, given } = require('sazerac');
-const { latest, slice, rangeStart } = require('./version');
-const includePre = true;
+const { test, given } = require('sazerac')
+const { latest, slice, rangeStart } = require('./version')
+const includePre = true
 
-describe('Version helpers', function () {
+describe('Version helpers', function() {
   test(latest, () => {
     // semver-compatible versions.
-    given(['1.0.0', '1.0.2', '1.0.1']).expect('1.0.2');
-    given(['1.0.0', '2.0.0', '3.0.0']).expect('3.0.0');
-    given(['0.0.1', '0.0.10', '0.0.2', '0.0.20']).expect('0.0.20');
+    given(['1.0.0', '1.0.2', '1.0.1']).expect('1.0.2')
+    given(['1.0.0', '2.0.0', '3.0.0']).expect('3.0.0')
+    given(['0.0.1', '0.0.10', '0.0.2', '0.0.20']).expect('0.0.20')
 
     // "not-quite-valid" semver versions
-    given(['1.0.00', '1.0.02', '1.0.01']).expect('1.0.02');
-    given(['1.0.05', '2.0.05', '3.0.05']).expect('3.0.05');
-    given(['0.0.01', '0.0.010', '0.0.02', '0.0.020']).expect('0.0.020');
+    given(['1.0.00', '1.0.02', '1.0.01']).expect('1.0.02')
+    given(['1.0.05', '2.0.05', '3.0.05']).expect('3.0.05')
+    given(['0.0.01', '0.0.010', '0.0.02', '0.0.020']).expect('0.0.020')
 
     // Mixed style versions. - include pre-releases
-    given(['1.0.0', 'v1.0.2', 'r1.0.1', 'release-2.0.0', 'v1.0.1-alpha.1'], { pre: includePre }).expect('release-2.0.0');
-    given(['1.0.0', 'v2.0.0', 'r1.0.1', 'release-1.0.3', 'v1.0.1-alpha.1'], { pre: includePre }).expect('v2.0.0');
-    given(['2.0.0', 'v1.0.3', 'r1.0.1', 'release-1.0.3', 'v1.0.1-alpha.1'], { pre: includePre }).expect('2.0.0');
-    given(['1.0.0', 'v1.0.2', 'r2.0.0', 'release-1.0.3', 'v1.0.1-alpha.1'], { pre: includePre }).expect('r2.0.0');
-    given(['1.0.0', 'v1.0.2', 'r2.0.0', 'release-1.0.3', 'v2.0.1-alpha.1'], { pre: includePre }).expect('v2.0.1-alpha.1');
+    given(['1.0.0', 'v1.0.2', 'r1.0.1', 'release-2.0.0', 'v1.0.1-alpha.1'], {
+      pre: includePre,
+    }).expect('release-2.0.0')
+    given(['1.0.0', 'v2.0.0', 'r1.0.1', 'release-1.0.3', 'v1.0.1-alpha.1'], {
+      pre: includePre,
+    }).expect('v2.0.0')
+    given(['2.0.0', 'v1.0.3', 'r1.0.1', 'release-1.0.3', 'v1.0.1-alpha.1'], {
+      pre: includePre,
+    }).expect('2.0.0')
+    given(['1.0.0', 'v1.0.2', 'r2.0.0', 'release-1.0.3', 'v1.0.1-alpha.1'], {
+      pre: includePre,
+    }).expect('r2.0.0')
+    given(['1.0.0', 'v1.0.2', 'r2.0.0', 'release-1.0.3', 'v2.0.1-alpha.1'], {
+      pre: includePre,
+    }).expect('v2.0.1-alpha.1')
 
     // Versions with 'v' prefix.
-    given(['v1.0.0', 'v1.0.2', 'v1.0.1']).expect('v1.0.2');
-    given(['v1.0.0', 'v3.0.0', 'v2.0.0']).expect('v3.0.0');
+    given(['v1.0.0', 'v1.0.2', 'v1.0.1']).expect('v1.0.2')
+    given(['v1.0.0', 'v3.0.0', 'v2.0.0']).expect('v3.0.0')
 
     // Simple (2 number) versions.
-    given(['0.1', '0.3', '0.2']).expect('0.3');
-    given(['0.1', '0.5', '0.12', '0.21']).expect('0.21');
-    given(['1.0', '2.0', '3.0']).expect('3.0');
+    given(['0.1', '0.3', '0.2']).expect('0.3')
+    given(['0.1', '0.5', '0.12', '0.21']).expect('0.21')
+    given(['1.0', '2.0', '3.0']).expect('3.0')
 
     // Simple (one-number) versions
-    given(['2', '10', '1']).expect('10');
+    given(['2', '10', '1']).expect('10')
 
     // Include pre-releases
-    given(['v1.0.1-alpha.2', 'v1.0.1-alpha.1', 'v1.0.1-beta.3', 'v1.0.1-beta.1', 'v1.0.1-RC.1', 'v1.0.1-RC.2', 'v1.0.0'], { pre: includePre }).expect('v1.0.1-RC.2');
-    given(['v1.0.1-alpha.2', 'v1.0.1-alpha.1', 'v1.0.1-beta.3', 'v1.0.1-beta.1', 'v1.0.1-RC.1', 'v1.0.1-RC.2','v1.0.1'], { pre: includePre }).expect('v1.0.1');
+    given(
+      [
+        'v1.0.1-alpha.2',
+        'v1.0.1-alpha.1',
+        'v1.0.1-beta.3',
+        'v1.0.1-beta.1',
+        'v1.0.1-RC.1',
+        'v1.0.1-RC.2',
+        'v1.0.0',
+      ],
+      { pre: includePre }
+    ).expect('v1.0.1-RC.2')
+    given(
+      [
+        'v1.0.1-alpha.2',
+        'v1.0.1-alpha.1',
+        'v1.0.1-beta.3',
+        'v1.0.1-beta.1',
+        'v1.0.1-RC.1',
+        'v1.0.1-RC.2',
+        'v1.0.1',
+      ],
+      { pre: includePre }
+    ).expect('v1.0.1')
     // Exclude pre-releases
-    given(['v1.0.1-alpha.2', 'v1.0.1-alpha.1', 'v1.0.1-beta.3', 'v1.0.1-beta.1', 'v1.0.1-RC.1', 'v1.0.1-RC.2', 'v1.0.0']).expect('v1.0.0');
-    given(['v1.0.1-alpha.2', 'v1.0.1-alpha.1', 'v1.0.1-beta.3', 'v1.0.1-beta.1', 'v1.0.1-RC.1', 'v1.0.1-RC.2','v1.0.1']).expect('v1.0.1');
+    given([
+      'v1.0.1-alpha.2',
+      'v1.0.1-alpha.1',
+      'v1.0.1-beta.3',
+      'v1.0.1-beta.1',
+      'v1.0.1-RC.1',
+      'v1.0.1-RC.2',
+      'v1.0.0',
+    ]).expect('v1.0.0')
+    given([
+      'v1.0.1-alpha.2',
+      'v1.0.1-alpha.1',
+      'v1.0.1-beta.3',
+      'v1.0.1-beta.1',
+      'v1.0.1-RC.1',
+      'v1.0.1-RC.2',
+      'v1.0.1',
+    ]).expect('v1.0.1')
 
     // Versions with 'release-' prefix
-    given(['release-1.0.0', 'release-1.0.2', 'release-1.0.20', 'release-1.0.3']).expect('release-1.0.20');
+    given([
+      'release-1.0.0',
+      'release-1.0.2',
+      'release-1.0.20',
+      'release-1.0.3',
+    ]).expect('release-1.0.20')
 
     // Semver mixed with non semver versions
-    given(['1.0.0', '1.0.2', '1.1', '1.0', 'notaversion2', '12bcde4']).expect('1.1');
-  });
+    given(['1.0.0', '1.0.2', '1.1', '1.0', 'notaversion2', '12bcde4']).expect(
+      '1.1'
+    )
+  })
 
   test(slice, () => {
-    given('2.4.7', 'major').expect('2');
-    given('2.4.7', 'minor').expect('2.4');
-    given('2.4.7', 'patch').expect('2.4.7');
-    given('02.4.7', 'major').expect('2');
-    given('2.04.7', 'minor').expect('2.4');
-    given('2.4.07', 'patch').expect('2.4.7');
-    given('2.4.7-alpha.1', 'major').expect('2-alpha.1');
-    given('2.4.7-alpha.1', 'minor').expect('2.4-alpha.1');
-    given('2.4.7-alpha.1', 'patch').expect('2.4.7-alpha.1');
-  });
+    given('2.4.7', 'major').expect('2')
+    given('2.4.7', 'minor').expect('2.4')
+    given('2.4.7', 'patch').expect('2.4.7')
+    given('02.4.7', 'major').expect('2')
+    given('2.04.7', 'minor').expect('2.4')
+    given('2.4.07', 'patch').expect('2.4.7')
+    given('2.4.7-alpha.1', 'major').expect('2-alpha.1')
+    given('2.4.7-alpha.1', 'minor').expect('2.4-alpha.1')
+    given('2.4.7-alpha.1', 'patch').expect('2.4.7-alpha.1')
+  })
 
   test(rangeStart, () => {
-    given('^2.4.7').expect('2.4.7');
-  });
-});
+    given('^2.4.7').expect('2.4.7')
+  })
+})
diff --git a/lib/vscode-badge-helpers.js b/lib/vscode-badge-helpers.js
index 9d5180fad5a6840086936436f80fce480294e153..3353cbbf535ee51f7d517b071b6daa4ffec289e5 100644
--- a/lib/vscode-badge-helpers.js
+++ b/lib/vscode-badge-helpers.js
@@ -1,39 +1,41 @@
-'use strict';
+'use strict'
 
 //To generate API request Options for VS Code marketplace
 function getVscodeApiReqOptions(packageName) {
   return {
     method: 'POST',
-    url: 'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery/',
-    headers:
-    {
-      'accept': 'application/json;api-version=3.0-preview.1',
-      'content-type': 'application/json'
+    url:
+      'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery/',
+    headers: {
+      accept: 'application/json;api-version=3.0-preview.1',
+      'content-type': 'application/json',
     },
-    body:
-    {
-      filters: [{
-        criteria: [
-          { filterType: 7, value: packageName }]
-      }],
-      flags: 914
+    body: {
+      filters: [
+        {
+          criteria: [{ filterType: 7, value: packageName }],
+        },
+      ],
+      flags: 914,
     },
-    json: true
-  };
+    json: true,
+  }
 }
 
 //To extract Statistics (Install/Rating/RatingCount) from respose object for vscode marketplace
 function getVscodeStatistic(data, statisticName) {
-  const statistics = data.results[0].extensions[0].statistics;
+  const statistics = data.results[0].extensions[0].statistics
   try {
-    const statistic = statistics.find(x => x.statisticName.toLowerCase() === statisticName.toLowerCase());
-    return statistic.value;
+    const statistic = statistics.find(
+      x => x.statisticName.toLowerCase() === statisticName.toLowerCase()
+    )
+    return statistic.value
   } catch (err) {
-    return 0; //In case required statistic is not found means ZERO.
+    return 0 //In case required statistic is not found means ZERO.
   }
 }
 
 module.exports = {
   getVscodeApiReqOptions,
-  getVscodeStatistic
-};
+  getVscodeStatistic,
+}
diff --git a/pages/index.js b/pages/index.js
index a23261aa3baf7ae87e262c293063b79ca4bc6738..453672773eabe9ea20690c5f5d529c61bef1bbba 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,26 +1,23 @@
-import React from 'react';
-import { HashRouter, StaticRouter, Route } from "react-router-dom";
-import ExamplesPage from '../frontend/components/examples-page';
-
+import React from 'react'
+import { HashRouter, StaticRouter, Route } from 'react-router-dom'
+import ExamplesPage from '../frontend/components/examples-page'
 
 export default class Router extends React.Component {
-
   render() {
     const router = (
       <div>
         <Route path="/" exact component={ExamplesPage} />
         <Route path="/examples/:id" component={ExamplesPage} />
       </div>
-    );
+    )
 
     if (typeof window !== 'undefined') {
       // browser
-      return (<HashRouter>{ router }</HashRouter>);
+      return <HashRouter>{router}</HashRouter>
     } else {
       // server-side rendering
-      const context = {};
-      return (<StaticRouter context={context}>{ router }</StaticRouter>);
+      const context = {}
+      return <StaticRouter context={context}>{router}</StaticRouter>
     }
   }
-
 }
diff --git a/services/amo/amo.tester.js b/services/amo/amo.tester.js
index 33ba7df665dcb4806bd3441a913f839adeb402df..b789210a01782ea69da6c09be9d2aad5adc37e8a 100644
--- a/services/amo/amo.tester.js
+++ b/services/amo/amo.tester.js
@@ -1,57 +1,65 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isMetric,
   isStarRating,
   isVPlusDottedVersionAtLeastOne,
-} = require('../test-validators');
+} = require('../test-validators')
 
-const t = new ServiceTester({ id: 'amo', title: 'Mozilla Addons' });
-module.exports = t;
+const t = new ServiceTester({ id: 'amo', title: 'Mozilla Addons' })
+module.exports = t
 
 t.create('Downloads')
   .get('/d/IndieGala-Helper.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }))
 
 t.create('Version')
   .get('/v/IndieGala-Helper.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'mozilla add-on',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'mozilla add-on',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('Version - Custom label')
   .get('/v/IndieGala-Helper.json?label=IndieGala Helper')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'IndieGala Helper',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'IndieGala Helper',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('Users')
   .get('/users/IndieGala-Helper.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'users',
-    value: Joi.string().regex(/^\d+$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'users',
+      value: Joi.string().regex(/^\d+$/),
+    })
+  )
 
 t.create('Rating')
   .get('/rating/IndieGala-Helper.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'rating',
-    value: Joi.string().regex(/^\d\/\d$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rating',
+      value: Joi.string().regex(/^\d\/\d$/),
+    })
+  )
 
 t.create('Stars')
   .get('/stars/IndieGala-Helper.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'stars', value: isStarRating }));
+  .expectJSONTypes(Joi.object().keys({ name: 'stars', value: isStarRating }))
 
 t.create('Invalid addon')
   .get('/d/invalid-name-of-addon.json')
-  .expectJSON({ name: 'mozilla add-on', value: 'invalid' });
+  .expectJSON({ name: 'mozilla add-on', value: 'invalid' })
 
 t.create('No connection')
   .get('/v/IndieGala-Helper.json')
   .networkOff()
-  .expectJSON({ name: 'mozilla add-on', value: 'inaccessible' });
+  .expectJSON({ name: 'mozilla add-on', value: 'inaccessible' })
diff --git a/services/ansible/ansible.tester.js b/services/ansible/ansible.tester.js
index bced90e3b06917fd3dcf96e7f6da403846219721..a8467d0286fc7224626482c588f0456ecb349306 100644
--- a/services/ansible/ansible.tester.js
+++ b/services/ansible/ansible.tester.js
@@ -1,33 +1,36 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isMetric } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isMetric } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'ansible', title: 'Ansible Galaxy' });
-module.exports = t;
+const t = new ServiceTester({ id: 'ansible', title: 'Ansible Galaxy' })
+module.exports = t
 
 t.create('ansible role name')
- .get('/role/14542.json')
- .expectJSON({ name: 'role', value: 'openwisp.openwisp2' });
+  .get('/role/14542.json')
+  .expectJSON({ name: 'role', value: 'openwisp.openwisp2' })
 
 t.create('ansible role download counts')
- .get('/role/d/14542.json')
- .expectJSONTypes(Joi.object().keys({ name: 'role downloads', value: isMetric }));
+  .get('/role/d/14542.json')
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'role downloads', value: isMetric })
+  )
 
 t.create('unkown role')
- .get('/role/000.json')
- .expectJSON({ name: 'role', value: 'not found' });
+  .get('/role/000.json')
+  .expectJSON({ name: 'role', value: 'not found' })
 
 t.create('connection error')
   .get('/role/14542.json')
   .networkOff()
-  .expectJSON({ name: 'role', value: 'errored' });
+  .expectJSON({ name: 'role', value: 'errored' })
 
 t.create('no response data')
   .get('/role/14542.json')
-  .intercept(nock => nock('https://galaxy.ansible.com')
-    .get('/api/v1/roles/14542/')
-    .reply(200)
+  .intercept(nock =>
+    nock('https://galaxy.ansible.com')
+      .get('/api/v1/roles/14542/')
+      .reply(200)
   )
-  .expectJSON({ name: 'role', value: 'not found' });
+  .expectJSON({ name: 'role', value: 'not found' })
diff --git a/services/apm/apm.service.js b/services/apm/apm.service.js
index 9c3d36a01fdc0eeba17d6e84c4fbcdd99220f73b..3f4ccbea254415d1a63f5662879242a1e260733b 100644
--- a/services/apm/apm.service.js
+++ b/services/apm/apm.service.js
@@ -1,137 +1,130 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const { BaseJsonService } = require('../base');
-const { InvalidResponse } = require('../errors');
-const { version: versionColor } = require('../../lib/color-formatters');
-const {
-  metric,
-  addv
-} = require('../../lib/text-formatters');
+const Joi = require('joi')
+const { BaseJsonService } = require('../base')
+const { InvalidResponse } = require('../errors')
+const { version: versionColor } = require('../../lib/color-formatters')
+const { metric, addv } = require('../../lib/text-formatters')
 
 class BaseAPMService extends BaseJsonService {
-
   async fetch(repo) {
     return this._requestJson({
       schema: Joi.object(),
       url: `https://atom.io/api/packages/${repo}`,
-      notFoundMessage: 'package not found'
-    });
+      notFoundMessage: 'package not found',
+    })
   }
 
   static get defaultBadgeData() {
-    return { label: 'apm' };
+    return { label: 'apm' }
   }
-
 }
 
 class APMDownloads extends BaseAPMService {
-  async handle({repo}) {
-    const json = await this.fetch(repo);
+  async handle({ repo }) {
+    const json = await this.fetch(repo)
 
-    const downloads = json.downloads;
-    return {message: metric(downloads), color: 'green'};
+    const downloads = json.downloads
+    return { message: metric(downloads), color: 'green' }
   }
 
   static get category() {
-    return 'downloads';
+    return 'downloads'
   }
 
   static get defaultBadgeData() {
-    return { label: 'downloads' };
+    return { label: 'downloads' }
   }
 
   static get url() {
     return {
       base: 'apm/dm',
       format: '(.+)',
-      capture: ['repo']
-    };
+      capture: ['repo'],
+    }
   }
 
   static get examples() {
     return [
       {
         previewUrl: 'dm/vim-mode',
-        keywords: [
-          'atom'
-        ]
+        keywords: ['atom'],
       },
-    ];
+    ]
   }
-};
+}
 
 class APMVersion extends BaseAPMService {
-  async handle({repo}) {
-    const json = await this.fetch(repo);
+  async handle({ repo }) {
+    const json = await this.fetch(repo)
 
-    const version = json.releases.latest;
+    const version = json.releases.latest
     if (!version)
-      throw new InvalidResponse({ underlyingError: new Error('version is invalid') });
-    return {message: addv(version), color: versionColor(version)};
+      throw new InvalidResponse({
+        underlyingError: new Error('version is invalid'),
+      })
+    return { message: addv(version), color: versionColor(version) }
   }
 
   static get category() {
-    return 'version';
+    return 'version'
   }
 
   static get url() {
     return {
       base: 'apm/v',
       format: '(.+)',
-      capture: ['repo']
-    };
+      capture: ['repo'],
+    }
   }
 
   static get examples() {
     return [
       {
         previewUrl: 'v/vim-mode',
-        keywords: [
-          'atom'
-        ]
+        keywords: ['atom'],
       },
-    ];
+    ]
   }
-};
+}
 
 class APMLicense extends BaseAPMService {
-  async handle({repo}) {
-    const json = await this.fetch(repo);
+  async handle({ repo }) {
+    const json = await this.fetch(repo)
 
-    const license = json.metadata.license;
+    const license = json.metadata.license
     if (!license)
-      throw new InvalidResponse({ underlyingError: new Error('licence is invalid') });
-    return {message: license, color: 'blue'};
+      throw new InvalidResponse({
+        underlyingError: new Error('licence is invalid'),
+      })
+    return { message: license, color: 'blue' }
   }
 
   static get defaultBadgeData() {
-    return { label: 'license' };
+    return { label: 'license' }
   }
 
   static get category() {
-    return 'license';
+    return 'license'
   }
 
   static get url() {
     return {
       base: 'apm/l',
       format: '(.+)',
-      capture: ['repo']
-    };
+      capture: ['repo'],
+    }
   }
 
   static get examples() {
     return [
       {
         previewUrl: 'l/vim-mode',
-        keywords: [
-          'atom'
-        ]
+        keywords: ['atom'],
       },
-    ];
+    ]
   }
-};
+}
 
 module.exports = {
   APMDownloads,
diff --git a/services/apm/apm.tester.js b/services/apm/apm.tester.js
index 048a6dc2672246446c1af965029fceb00dd36538..78cb27c09e1181f8de7579f5cbf4e128306f8161 100644
--- a/services/apm/apm.tester.js
+++ b/services/apm/apm.tester.js
@@ -1,70 +1,66 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const t = new ServiceTester({ id: 'apm', title: 'Atom Package Manager' });
-const { invalidJSON } = require('../response-fixtures');
-const {
-  isMetric,
-  isVPlusTripleDottedVersion
-} = require('../test-validators');
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const t = new ServiceTester({ id: 'apm', title: 'Atom Package Manager' })
+const { invalidJSON } = require('../response-fixtures')
+const { isMetric, isVPlusTripleDottedVersion } = require('../test-validators')
+module.exports = t
 
 t.create('Downloads')
   .get('/dm/vim-mode.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }))
 
 t.create('Version')
   .get('/v/vim-mode.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'apm', value: isVPlusTripleDottedVersion }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'apm', value: isVPlusTripleDottedVersion })
+  )
 
 t.create('License')
   .get('/l/vim-mode.json')
-  .expectJSON({ name: 'license', value: 'MIT' });
+  .expectJSON({ name: 'license', value: 'MIT' })
 
 t.create('Downloads | Package not found')
   .get('/dm/notapackage.json')
-  .expectJSON({ name: 'downloads', value: 'package not found' });
+  .expectJSON({ name: 'downloads', value: 'package not found' })
 
 t.create('Version | Package not found')
   .get('/v/notapackage.json')
-  .expectJSON({ name: 'apm', value: 'package not found' });
+  .expectJSON({ name: 'apm', value: 'package not found' })
 
 t.create('License | Package not found')
   .get('/l/notapackage.json')
-  .expectJSON({ name: 'license', value: 'package not found' });
+  .expectJSON({ name: 'license', value: 'package not found' })
 
 t.create('Connection error')
   .get('/v/vim-mode.json')
   .networkOff()
-  .expectJSON({ name: 'apm', value: 'inaccessible' });
+  .expectJSON({ name: 'apm', value: 'inaccessible' })
 
 t.create('Invalid version')
   .get('/dm/vim-mode.json')
-  .intercept(nock => nock('https://atom.io')
-    .get('/api/packages/vim-mode')
-    .reply([
-      200,
-      '{"releases":{}}'
-    ])
+  .intercept(nock =>
+    nock('https://atom.io')
+      .get('/api/packages/vim-mode')
+      .reply([200, '{"releases":{}}'])
   )
-  .expectJSON({name: 'downloads', value: 'unparseable json response'});
+  .expectJSON({ name: 'downloads', value: 'unparseable json response' })
 
 t.create('Invalid License')
   .get('/l/vim-mode.json')
-  .intercept(nock => nock('https://atom.io')
-    .get('/api/packages/vim-mode')
-    .reply([
-      200,
-      '{"metadata":{}}'
-    ])
+  .intercept(nock =>
+    nock('https://atom.io')
+      .get('/api/packages/vim-mode')
+      .reply([200, '{"metadata":{}}'])
   )
-  .expectJSON({name: 'license', value: 'unparseable json response'});
+  .expectJSON({ name: 'license', value: 'unparseable json response' })
 
 t.create('Unexpected response')
   .get('/dm/vim-mode.json')
-  .intercept(nock => nock('https://atom.io')
-    .get('/api/packages/vim-mode')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://atom.io')
+      .get('/api/packages/vim-mode')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'downloads', value: 'unparseable json response'});
+  .expectJSON({ name: 'downloads', value: 'unparseable json response' })
diff --git a/services/appveyor/appveyor.service.js b/services/appveyor/appveyor.service.js
index 820231c91c3bfecfd3dd8c8852360ccb11b1f706..220cc3d2b280ea03b56e056a580666a47fe7d17b 100644
--- a/services/appveyor/appveyor.service.js
+++ b/services/appveyor/appveyor.service.js
@@ -1,40 +1,42 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const { BaseJsonService } = require('../base');
+const Joi = require('joi')
+const { BaseJsonService } = require('../base')
 
 module.exports = class AppVeyor extends BaseJsonService {
-  async handle({repo, branch}) {
-    let url = `https://ci.appveyor.com/api/projects/${repo}`;
+  async handle({ repo, branch }) {
+    let url = `https://ci.appveyor.com/api/projects/${repo}`
     if (branch != null) {
-      url += `/branch/${branch}`;
+      url += `/branch/${branch}`
     }
-    const { build: { status } } = await this._requestJson({
+    const {
+      build: { status },
+    } = await this._requestJson({
       schema: Joi.object(),
       url,
       notFoundMessage: 'project not found or access denied',
-    });
+    })
 
     if (status === 'success') {
-      return {message: 'passing', color: 'brightgreen'};
+      return { message: 'passing', color: 'brightgreen' }
     } else if (status !== 'running' && status !== 'queued') {
-      return {message: 'failing', color: 'red'};
+      return { message: 'failing', color: 'red' }
     } else {
-      return {message: status};
+      return { message: status }
     }
   }
 
   // Metadata
   static get category() {
-    return 'build';
+    return 'build'
   }
 
   static get url() {
     return {
       base: 'appveyor/ci',
       format: '([^/]+/[^/]+)(?:/(.+))?',
-      capture: ['repo', 'branch']
-    };
+      capture: ['repo', 'branch'],
+    }
   }
 
   static get examples() {
@@ -46,6 +48,6 @@ module.exports = class AppVeyor extends BaseJsonService {
         title: `${this.name} branch`,
         previewUrl: 'gruntjs/grunt/master',
       },
-    ];
+    ]
   }
-};
+}
diff --git a/services/appveyor/appveyor.tester.js b/services/appveyor/appveyor.tester.js
index 5e2299e14d385acaaa1606c13f9069a6bc6860cb..7be77fd216838093dc71362fa418cf44f47ff69b 100644
--- a/services/appveyor/appveyor.tester.js
+++ b/services/appveyor/appveyor.tester.js
@@ -1,46 +1,51 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const { isBuildStatus } = require('../test-validators');
-const isAppveyorTestTotals =
-  Joi.string().regex(/^(?:[0-9]+ (?:passed|skipped|failed)(?:, )?)+$/);
+const { isBuildStatus } = require('../test-validators')
+const isAppveyorTestTotals = Joi.string().regex(
+  /^(?:[0-9]+ (?:passed|skipped|failed)(?:, )?)+$/
+)
 
-const t = new ServiceTester({ id: 'appveyor', title: 'AppVeyor' });
-module.exports = t;
+const t = new ServiceTester({ id: 'appveyor', title: 'AppVeyor' })
+module.exports = t
 
 // Test AppVeyor build status badge
 t.create('CI build status')
   .get('/ci/gruntjs/grunt.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'build', value: isBuildStatus }));
+  .expectJSONTypes(Joi.object().keys({ name: 'build', value: isBuildStatus }))
 
 // Test AppVeyor branch build status badge
 t.create('CI build status on master branch')
   .get('/ci/gruntjs/grunt/master.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'build', value: isBuildStatus }));
+  .expectJSONTypes(Joi.object().keys({ name: 'build', value: isBuildStatus }))
 
 // Test AppVeyor build status badge on a non-existing project
 t.create('CI 404')
-.get('/ci/somerandomproject/thatdoesntexits.json')
-  .expectJSON({ name: 'build', value: 'project not found or access denied' });
+  .get('/ci/somerandomproject/thatdoesntexits.json')
+  .expectJSON({ name: 'build', value: 'project not found or access denied' })
 
 t.create('CI (connection error)')
   .get('/ci/this-one/is-not-real-either.json')
   .networkOff()
-  .expectJSON({ name: 'build', value: 'inaccessible' });
+  .expectJSON({ name: 'build', value: 'inaccessible' })
 
 // Test AppVeyor tests status badge
 t.create('tests status')
   .get('/tests/NZSmartie/coap-net-iu0to.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'tests', value: isAppveyorTestTotals }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'tests', value: isAppveyorTestTotals })
+  )
 
 // Test AppVeyor branch tests status badge
 t.create('tests status on master branch')
   .get('/tests/NZSmartie/coap-net-iu0to/master.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'tests', value: isAppveyorTestTotals }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'tests', value: isAppveyorTestTotals })
+  )
 
 // Test AppVeyor tests status badge for a non-existing project
 t.create('tests 404')
   .get('/tests/somerandomproject/thatdoesntexits.json')
-  .expectJSON({ name: 'tests', value: 'project not found or access denied' });
+  .expectJSON({ name: 'tests', value: 'project not found or access denied' })
diff --git a/services/aur/aur.tester.js b/services/aur/aur.tester.js
index 5e7e3a0647ec1852ef82e43e41be5976771dd035..4c8d109f97d67132f13c32c0606f9ecb4eb4add2 100644
--- a/services/aur/aur.tester.js
+++ b/services/aur/aur.tester.js
@@ -1,121 +1,131 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'aur', title: 'Arch Linux AUR' });
-module.exports = t;
+} = require('../test-validators')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'aur', title: 'Arch Linux AUR' })
+module.exports = t
 
 // version tests
 
 t.create('version (valid)')
   .get('/version/yaourt.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'AUR',
-    value: isVPlusDottedVersionNClausesWithOptionalSuffix,
-    colorB: '#007ec6',
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'AUR',
+      value: isVPlusDottedVersionNClausesWithOptionalSuffix,
+      colorB: '#007ec6',
+    })
+  )
 
 t.create('version (valid, out of date)')
   .get('/version/gog-gemini-rue.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'AUR',
-    value: isVPlusDottedVersionNClausesWithOptionalSuffix,
-    colorB: '#fe7d37',
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'AUR',
+      value: isVPlusDottedVersionNClausesWithOptionalSuffix,
+      colorB: '#fe7d37',
+    })
+  )
 
 t.create('version (not found)')
   .get('/version/not-a-package.json')
-  .expectJSON({name: 'AUR', value: 'not found'});
+  .expectJSON({ name: 'AUR', value: 'not found' })
 
 t.create('version (connection error)')
   .get('/version/yaourt.json')
   .networkOff()
-  .expectJSON({name: 'AUR', value: 'inaccessible'});
+  .expectJSON({ name: 'AUR', value: 'inaccessible' })
 
 t.create('version (unexpected response)')
   .get('/version/yaourt.json')
-  .intercept(nock => nock('https://aur.archlinux.org')
-    .get('/rpc.php?type=info&arg=yaourt')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://aur.archlinux.org')
+      .get('/rpc.php?type=info&arg=yaourt')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'AUR', value: 'invalid'});
+  .expectJSON({ name: 'AUR', value: 'invalid' })
 
 t.create('version (error response)')
   .get('/version/yaourt.json')
-  .intercept(nock => nock('https://aur.archlinux.org')
-    .get('/rpc.php?type=info&arg=yaourt')
-    .reply(500, '{"error":"oh noes!!"}')
+  .intercept(nock =>
+    nock('https://aur.archlinux.org')
+      .get('/rpc.php?type=info&arg=yaourt')
+      .reply(500, '{"error":"oh noes!!"}')
   )
-  .expectJSON({name: 'AUR', value: 'invalid'});
+  .expectJSON({ name: 'AUR', value: 'invalid' })
 
 // votes tests
 
 t.create('votes (valid)')
   .get('/votes/yaourt.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'votes',
-    value: Joi.number().integer(),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'votes',
+      value: Joi.number().integer(),
+    })
+  )
 
 t.create('votes (not found)')
   .get('/votes/not-a-package.json')
-  .expectJSON({name: 'AUR', value: 'not found'});
+  .expectJSON({ name: 'AUR', value: 'not found' })
 
 t.create('votes (connection error)')
   .get('/votes/yaourt.json')
   .networkOff()
-  .expectJSON({name: 'AUR', value: 'inaccessible'});
+  .expectJSON({ name: 'AUR', value: 'inaccessible' })
 
 t.create('votes (unexpected response)')
   .get('/votes/yaourt.json')
-  .intercept(nock => nock('https://aur.archlinux.org')
-    .get('/rpc.php?type=info&arg=yaourt')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://aur.archlinux.org')
+      .get('/rpc.php?type=info&arg=yaourt')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'AUR', value: 'invalid'});
+  .expectJSON({ name: 'AUR', value: 'invalid' })
 
 t.create('votes (error response)')
   .get('/votes/yaourt.json')
-  .intercept(nock => nock('https://aur.archlinux.org')
-    .get('/rpc.php?type=info&arg=yaourt')
-    .reply(500, '{"error":"oh noes!!"}')
+  .intercept(nock =>
+    nock('https://aur.archlinux.org')
+      .get('/rpc.php?type=info&arg=yaourt')
+      .reply(500, '{"error":"oh noes!!"}')
   )
-  .expectJSON({name: 'AUR', value: 'invalid'});
-
+  .expectJSON({ name: 'AUR', value: 'invalid' })
 
 // license tests
 
 t.create('license (valid)')
   .get('/license/yaourt.json')
-  .expectJSON({name: 'license', value: 'GPL'});
+  .expectJSON({ name: 'license', value: 'GPL' })
 
 t.create('license (not found)')
   .get('/license/not-a-package.json')
-  .expectJSON({name: 'AUR', value: 'not found'});
+  .expectJSON({ name: 'AUR', value: 'not found' })
 
 t.create('license (connection error)')
   .get('/license/yaourt.json')
   .networkOff()
-  .expectJSON({name: 'AUR', value: 'inaccessible'});
+  .expectJSON({ name: 'AUR', value: 'inaccessible' })
 
 t.create('license (unexpected response)')
   .get('/license/yaourt.json')
-  .intercept(nock => nock('https://aur.archlinux.org')
-    .get('/rpc.php?type=info&arg=yaourt')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://aur.archlinux.org')
+      .get('/rpc.php?type=info&arg=yaourt')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'AUR', value: 'invalid'});
+  .expectJSON({ name: 'AUR', value: 'invalid' })
 
 t.create('license (error response)')
   .get('/license/yaourt.json')
-  .intercept(nock => nock('https://aur.archlinux.org')
-    .get('/rpc.php?type=info&arg=yaourt')
-    .reply(500, '{"error":"oh noes!!"}')
+  .intercept(nock =>
+    nock('https://aur.archlinux.org')
+      .get('/rpc.php?type=info&arg=yaourt')
+      .reply(500, '{"error":"oh noes!!"}')
   )
-  .expectJSON({name: 'AUR', value: 'invalid'});
+  .expectJSON({ name: 'AUR', value: 'invalid' })
diff --git a/services/base-json.spec.js b/services/base-json.spec.js
index d030b7f7d08c2dd8b6e02bb7c810bb10f8b7cf56..012e718da0a73d0c0a18b6dcec6d22c97cfb4a37 100644
--- a/services/base-json.spec.js
+++ b/services/base-json.spec.js
@@ -1,28 +1,28 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const chai = require('chai');
-const { expect } = chai;
+const Joi = require('joi')
+const chai = require('chai')
+const { expect } = chai
 
-const { BaseJsonService } = require('./base');
-const { invalidJSON } = require('./response-fixtures');
+const { BaseJsonService } = require('./base')
+const { invalidJSON } = require('./response-fixtures')
 
-chai.use(require('chai-as-promised'));
+chai.use(require('chai-as-promised'))
 
 class DummyJsonService extends BaseJsonService {
   static get category() {
-    return 'cat';
+    return 'cat'
   }
 
   static get url() {
     return {
       base: 'foo',
-    };
+    }
   }
 
   async handle() {
-    const { value } = await this._requestJson({ schema: Joi.any() });
-    return { message: value };
+    const { value } = await this._requestJson({ schema: Joi.any() })
+    return { message: value }
   }
 }
 
@@ -31,30 +31,30 @@ describe('BaseJsonService', () => {
     const sendAndCacheRequest = async () => ({
       buffer: invalidJSON,
       res: { statusCode: 200 },
-    });
+    })
     const serviceInstance = new DummyJsonService(
       { sendAndCacheRequest },
       { handleInternalErrors: false }
-    );
+    )
     const serviceData = await serviceInstance.invokeHandler(
       { schema: Joi.any() },
       {}
-    );
+    )
     expect(serviceData).to.deep.equal({
       color: 'lightgray',
       message: 'unparseable json response',
-    });
-  });
+    })
+  })
 
   context('a schema is not provided', function() {
     it('throws the expected error', async function() {
       const serviceInstance = new DummyJsonService(
         {},
         { handleInternalErrors: false }
-      );
+      )
       expect(
         serviceInstance._requestJson({ schema: undefined })
-      ).to.be.rejectedWith('A Joi schema is required');
-    });
-  });
-});
+      ).to.be.rejectedWith('A Joi schema is required')
+    })
+  })
+})
diff --git a/services/base.js b/services/base.js
index adce94feed2c75935e8d6e3363413f2ecc054548..a5450c6ea6a0da58efbd6592bd1ca8f209c69a88 100644
--- a/services/base.js
+++ b/services/base.js
@@ -1,34 +1,26 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const {
-  NotFound,
-  InvalidResponse,
-  Inaccessible,
-} = require('./errors');
-const queryString = require('query-string');
+const Joi = require('joi')
+const { NotFound, InvalidResponse, Inaccessible } = require('./errors')
+const queryString = require('query-string')
 const {
   makeLogo,
   toArray,
   makeColor,
   setBadgeColor,
-} = require('../lib/badge-data');
-const {
-  checkErrorResponse,
-  asJson,
-} = require('../lib/error-helper');
-
+} = require('../lib/badge-data')
+const { checkErrorResponse, asJson } = require('../lib/error-helper')
 
 class BaseService {
   constructor({ sendAndCacheRequest }, { handleInternalErrors }) {
-    this._sendAndCacheRequest = sendAndCacheRequest;
-    this._handleInternalErrors = handleInternalErrors;
+    this._sendAndCacheRequest = sendAndCacheRequest
+    this._handleInternalErrors = handleInternalErrors
   }
 
   static render(props) {
     throw new Error(
       `render() function not implemented for ${this.constructor.name}`
-    );
+    )
   }
 
   /**
@@ -37,9 +29,7 @@ class BaseService {
    * `this._sendAndCacheRequest`, and returns the badge data.
    */
   async handle(namedParams, queryParams) {
-    throw new Error(
-      `Handler not implemented for ${this.constructor.name}`
-    );
+    throw new Error(`Handler not implemented for ${this.constructor.name}`)
   }
 
   // Metadata
@@ -49,7 +39,7 @@ class BaseService {
    * the badges on the main shields.io website.
    */
   static get category() {
-    return 'unknown';
+    return 'unknown'
   }
 
   /**
@@ -65,7 +55,7 @@ class BaseService {
    *                 parameters will be passed to the handler.
    */
   static get url() {
-    throw new Error(`URL not defined for ${this.name}`);
+    throw new Error(`URL not defined for ${this.name}`)
   }
 
   /**
@@ -74,7 +64,7 @@ class BaseService {
    * by either the handler or by the user via URL parameters.
    */
   static get defaultBadgeData() {
-    return {};
+    return {}
   }
 
   /**
@@ -83,11 +73,11 @@ class BaseService {
    * this service.
    */
   static get examples() {
-    return [];
+    return []
   }
 
   static _makeFullUrl(partialUrl) {
-    return '/' + [this.url.base, partialUrl].filter(Boolean).join('/');
+    return '/' + [this.url.base, partialUrl].filter(Boolean).join('/')
   }
 
   /**
@@ -102,13 +92,11 @@ class BaseService {
     return this.examples.map(
       ({ title, previewUrl, query, exampleUrl, documentation }) => {
         if (!previewUrl) {
-          throw Error(
-            `Example for ${this.name} is missing required previewUrl`
-          );
+          throw Error(`Example for ${this.name} is missing required previewUrl`)
         }
 
-        const stringified = queryString.stringify(query);
-        const suffix = stringified ? `?${stringified}` : '';
+        const stringified = queryString.stringify(query)
+        const suffix = stringified ? `?${stringified}` : ''
 
         return {
           title: title ? `${title}` : this.name,
@@ -117,61 +105,67 @@ class BaseService {
             ? `${this._makeFullUrl(exampleUrl, query)}.svg${suffix}`
             : undefined,
           documentation,
-        };
+        }
       }
-    );
+    )
   }
 
   static get _regex() {
     // Regular expressions treat "/" specially, so we need to escape them
-    const escapedPath = this.url.format.replace(/\//g, '\\/');
-    const fullRegex = `^${this._makeFullUrl(escapedPath)}.(svg|png|gif|jpg|json)$`;
-    return new RegExp(fullRegex);
+    const escapedPath = this.url.format.replace(/\//g, '\\/')
+    const fullRegex = `^${this._makeFullUrl(
+      escapedPath
+    )}.(svg|png|gif|jpg|json)$`
+    return new RegExp(fullRegex)
   }
 
   static _namedParamsForMatch(match) {
     // Assume the last match is the format, and drop match[0], which is the
     // entire match.
-    const captures = match.slice(1, -1);
+    const captures = match.slice(1, -1)
 
     if (this.url.capture.length !== captures.length) {
       throw new Error(
-        `Service ${this.constructor.name} declares incorrect number of capture groups `+
-        `(expected ${this.url.capture.length}, got ${captures.length})`
-      );
+        `Service ${
+          this.constructor.name
+        } declares incorrect number of capture groups ` +
+          `(expected ${this.url.capture.length}, got ${captures.length})`
+      )
     }
 
-    const result = {};
+    const result = {}
     this.url.capture.forEach((name, index) => {
-      result[name] = captures[index];
-    });
-    return result;
+      result[name] = captures[index]
+    })
+    return result
   }
 
   async invokeHandler(namedParams, queryParams) {
     try {
-      return await this.handle(namedParams, queryParams);
+      return await this.handle(namedParams, queryParams)
     } catch (error) {
       if (error instanceof NotFound) {
         return {
           message: error.prettyMessage,
           color: 'red',
-        };
-      } else if (error instanceof InvalidResponse ||
-        error instanceof Inaccessible) {
+        }
+      } else if (
+        error instanceof InvalidResponse ||
+        error instanceof Inaccessible
+      ) {
         return {
           message: error.prettyMessage,
           color: 'lightgray',
-        };
+        }
       } else if (this._handleInternalErrors) {
-        console.log(error);
+        console.log(error)
         return {
           label: 'shields',
           message: 'internal error',
           color: 'lightgray',
-        };
+        }
       } else {
-        throw error;
+        throw error
       }
     }
   }
@@ -185,20 +179,20 @@ class BaseService {
       link: overrideLink,
       colorA: overrideColorA,
       colorB: overrideColorB,
-    } = overrides;
+    } = overrides
 
     const {
       label: serviceLabel,
       message: serviceMessage,
       color: serviceColor,
       link: serviceLink,
-    } = serviceData;
+    } = serviceData
 
     const {
       color: defaultColor,
       logo: defaultLogo,
       label: defaultLabel,
-    } = this.defaultBadgeData;
+    } = this.defaultBadgeData
 
     const badgeData = {
       text: [
@@ -206,35 +200,46 @@ class BaseService {
         serviceMessage || 'n/a',
       ],
       template: style,
-      logo: makeLogo(style === 'social' ? defaultLogo : undefined, { logo: overrideLogo }),
+      logo: makeLogo(style === 'social' ? defaultLogo : undefined, {
+        logo: overrideLogo,
+      }),
       logoWidth: +overrideLogoWidth,
       links: toArray(overrideLink || serviceLink),
       colorA: makeColor(overrideColorA),
-    };
-    const color = overrideColorB || serviceColor || defaultColor || 'lightgrey';
-    setBadgeColor(badgeData, color);
+    }
+    const color = overrideColorB || serviceColor || defaultColor || 'lightgrey'
+    setBadgeColor(badgeData, color)
 
-    return badgeData;
+    return badgeData
   }
 
   static register(camp, handleRequest, { handleInternalErrors }) {
-    const ServiceClass = this; // In a static context, "this" is the class.
+    const ServiceClass = this // In a static context, "this" is the class.
 
-    camp.route(this._regex, handleRequest({
-      queryParams: this.url.queryParams,
-      handler: async (queryParams, match, sendBadge, request) => {
-        const namedParams = this._namedParamsForMatch(match);
-        const serviceInstance = new ServiceClass({
-          sendAndCacheRequest: request.asPromise,
-        }, { handleInternalErrors });
-        const serviceData = await serviceInstance.invokeHandler(namedParams, queryParams);
-        const badgeData = this._makeBadgeData(queryParams, serviceData);
+    camp.route(
+      this._regex,
+      handleRequest({
+        queryParams: this.url.queryParams,
+        handler: async (queryParams, match, sendBadge, request) => {
+          const namedParams = this._namedParamsForMatch(match)
+          const serviceInstance = new ServiceClass(
+            {
+              sendAndCacheRequest: request.asPromise,
+            },
+            { handleInternalErrors }
+          )
+          const serviceData = await serviceInstance.invokeHandler(
+            namedParams,
+            queryParams
+          )
+          const badgeData = this._makeBadgeData(queryParams, serviceData)
 
-        // Assumes the final capture group is the extension
-        const format = match.slice(-1)[0];
-        sendBadge(format, badgeData);
-      },
-    }));
+          // Assumes the final capture group is the extension
+          const format = match.slice(-1)[0]
+          sendBadge(format, badgeData)
+        },
+      })
+    )
   }
 }
 
@@ -243,33 +248,36 @@ class BaseJsonService extends BaseService {
     const { error, value } = Joi.validate(json, schema, {
       allowUnknown: true,
       stripUnknown: true,
-    });
+    })
     if (error) {
       throw new InvalidResponse({
         prettyMessage: 'invalid json response',
         underlyingError: error,
-      });
+      })
     } else {
-      return value;
+      return value
     }
   }
 
   async _requestJson({ schema, url, options = {}, notFoundMessage }) {
-    if (! schema || ! schema.isJoi) {
-      throw Error('A Joi schema is required');
+    if (!schema || !schema.isJoi) {
+      throw Error('A Joi schema is required')
     }
-    return this._sendAndCacheRequest(url,
-      {...{ 'headers': { 'Accept': 'application/json' } }, ...options}
-    ).then(
-      checkErrorResponse.asPromise(
-        notFoundMessage ? { notFoundMessage: notFoundMessage } : undefined
+    return this._sendAndCacheRequest(url, {
+      ...{ headers: { Accept: 'application/json' } },
+      ...options,
+    })
+      .then(
+        checkErrorResponse.asPromise(
+          notFoundMessage ? { notFoundMessage: notFoundMessage } : undefined
+        )
       )
-    ).then(asJson)
-     .then(json => this.constructor._validate(json, schema));
+      .then(asJson)
+      .then(json => this.constructor._validate(json, schema))
   }
 }
 
 module.exports = {
   BaseService,
   BaseJsonService,
-};
+}
diff --git a/services/base.spec.js b/services/base.spec.js
index 3ddbbc723b7a4869e3bf3383780d5c46d514b555..b553f43f6af6a8a548fc21d8d25af7092415058e 100644
--- a/services/base.spec.js
+++ b/services/base.spec.js
@@ -1,24 +1,26 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const { test, given, forCases } = require('sazerac');
-const sinon = require('sinon');
+const { expect } = require('chai')
+const { test, given, forCases } = require('sazerac')
+const sinon = require('sinon')
 
-const { BaseService } = require('./base');
+const { BaseService } = require('./base')
 
-require('../lib/register-chai-plugins.spec');
+require('../lib/register-chai-plugins.spec')
 
 class DummyService extends BaseService {
   async handle({ namedParamA }, { queryParamA }) {
-    return { message: `Hello ${namedParamA}${queryParamA}` };
+    return { message: `Hello ${namedParamA}${queryParamA}` }
   }
 
-  static get category() { return 'cat'; }
+  static get category() {
+    return 'cat'
+  }
   static get examples() {
     return [
       { previewUrl: 'World' },
       { previewUrl: 'World', query: { queryParamA: '!!!' } },
-    ];
+    ]
   }
   static get url() {
     return {
@@ -26,30 +28,30 @@ class DummyService extends BaseService {
       format: '([^/]+)',
       capture: ['namedParamA'],
       queryParams: ['queryParamA'],
-    };
+    }
   }
 }
 
 describe('BaseService', () => {
-  const defaultConfig = { handleInternalErrors: false };
+  const defaultConfig = { handleInternalErrors: false }
 
-  describe('URL pattern matching', function () {
-    const regexExec = str => DummyService._regex.exec(str);
+  describe('URL pattern matching', function() {
+    const regexExec = str => DummyService._regex.exec(str)
     const getNamedParamA = str => {
-      const [, namedParamA] = regexExec(str);
-      return namedParamA;
-    };
+      const [, namedParamA] = regexExec(str)
+      return namedParamA
+    }
     const namedParams = str => {
-      const match = regexExec(str);
-      return DummyService._namedParamsForMatch(match);
-    };
+      const match = regexExec(str)
+      return DummyService._namedParamsForMatch(match)
+    }
 
     test(regexExec, () => {
       forCases([
         given('/foo/bar.bar.bar.zip'),
         given('/foo/bar/bar.svg'),
-      ]).expect(null);
-    });
+      ]).expect(null)
+    })
 
     test(getNamedParamA, () => {
       forCases([
@@ -58,8 +60,8 @@ describe('BaseService', () => {
         given('/foo/bar.bar.bar.gif'),
         given('/foo/bar.bar.bar.jpg'),
         given('/foo/bar.bar.bar.json'),
-      ]).expect('bar.bar.bar');
-    });
+      ]).expect('bar.bar.bar')
+    })
 
     test(namedParams, () => {
       forCases([
@@ -68,132 +70,143 @@ describe('BaseService', () => {
         given('/foo/bar.bar.bar.gif'),
         given('/foo/bar.bar.bar.jpg'),
         given('/foo/bar.bar.bar.json'),
-      ]).expect({ namedParamA: 'bar.bar.bar' });
-    });
-  });
+      ]).expect({ namedParamA: 'bar.bar.bar' })
+    })
+  })
 
-  it('Invokes the handler as expected', async function () {
-    const serviceInstance = new DummyService({}, defaultConfig);
+  it('Invokes the handler as expected', async function() {
+    const serviceInstance = new DummyService({}, defaultConfig)
     const serviceData = await serviceInstance.invokeHandler(
       { namedParamA: 'bar.bar.bar' },
-      { queryParamA: '!' });
-    expect(serviceData).to.deep.equal({ message: 'Hello bar.bar.bar!' });
-  });
-
-  describe('Error handling', function () {
-    it('Handles internal errors', async function () {
-      const serviceInstance = new DummyService({}, { handleInternalErrors: true });
-      serviceInstance.handle = () => { throw Error("I've made a huge mistake"); };
-      const serviceData = await serviceInstance.invokeHandler({ namedParamA: 'bar.bar.bar' });
+      { queryParamA: '!' }
+    )
+    expect(serviceData).to.deep.equal({ message: 'Hello bar.bar.bar!' })
+  })
+
+  describe('Error handling', function() {
+    it('Handles internal errors', async function() {
+      const serviceInstance = new DummyService(
+        {},
+        { handleInternalErrors: true }
+      )
+      serviceInstance.handle = () => {
+        throw Error("I've made a huge mistake")
+      }
+      const serviceData = await serviceInstance.invokeHandler({
+        namedParamA: 'bar.bar.bar',
+      })
       expect(serviceData).to.deep.equal({
         color: 'lightgray',
         label: 'shields',
         message: 'internal error',
-      });
-    });
-  });
-
-  describe('_makeBadgeData', function () {
-    describe('Overrides', function () {
-      it('overrides the label', function () {
-        const badgeData = DummyService._makeBadgeData({ label: 'purr count' }, { label: 'purrs' });
-        expect(badgeData.text).to.deep.equal(['purr count', 'n/a']);
-      });
-
-      it('overrides the color', function () {
-        const badgeData = DummyService._makeBadgeData({ colorB: '10ADED' }, { color: 'red' });
-        expect(badgeData.colorB).to.equal('#10ADED');
-      });
-    });
-
-    describe('Service data', function () {
-      it('applies the service message', function () {
-        const badgeData = DummyService._makeBadgeData({}, { message: '10k' });
-        expect(badgeData.text).to.deep.equal(['cat', '10k']);
-      });
-
-      it('applies the service color', function () {
-        const badgeData = DummyService._makeBadgeData({}, { color: 'red' });
-        expect(badgeData.colorscheme).to.equal('red');
-      });
-    });
-
-    describe('Defaults', function () {
-      it('uses the default label', function () {
-        const badgeData = DummyService._makeBadgeData({}, {});
-        expect(badgeData.text).to.deep.equal(['cat', 'n/a']);
-      });
-
-      it('uses the default color', function () {
-        const badgeData = DummyService._makeBadgeData({}, {});
-        expect(badgeData.colorscheme).to.equal('lightgrey');
-      });
-    });
-  });
-
-  describe('ScoutCamp integration', function () {
-    const expectedRouteRegex = /^\/foo\/([^/]+).(svg|png|gif|jpg|json)$/;
-
-    let mockCamp;
-    let mockHandleRequest;
+      })
+    })
+  })
+
+  describe('_makeBadgeData', function() {
+    describe('Overrides', function() {
+      it('overrides the label', function() {
+        const badgeData = DummyService._makeBadgeData(
+          { label: 'purr count' },
+          { label: 'purrs' }
+        )
+        expect(badgeData.text).to.deep.equal(['purr count', 'n/a'])
+      })
+
+      it('overrides the color', function() {
+        const badgeData = DummyService._makeBadgeData(
+          { colorB: '10ADED' },
+          { color: 'red' }
+        )
+        expect(badgeData.colorB).to.equal('#10ADED')
+      })
+    })
+
+    describe('Service data', function() {
+      it('applies the service message', function() {
+        const badgeData = DummyService._makeBadgeData({}, { message: '10k' })
+        expect(badgeData.text).to.deep.equal(['cat', '10k'])
+      })
+
+      it('applies the service color', function() {
+        const badgeData = DummyService._makeBadgeData({}, { color: 'red' })
+        expect(badgeData.colorscheme).to.equal('red')
+      })
+    })
+
+    describe('Defaults', function() {
+      it('uses the default label', function() {
+        const badgeData = DummyService._makeBadgeData({}, {})
+        expect(badgeData.text).to.deep.equal(['cat', 'n/a'])
+      })
+
+      it('uses the default color', function() {
+        const badgeData = DummyService._makeBadgeData({}, {})
+        expect(badgeData.colorscheme).to.equal('lightgrey')
+      })
+    })
+  })
+
+  describe('ScoutCamp integration', function() {
+    const expectedRouteRegex = /^\/foo\/([^/]+).(svg|png|gif|jpg|json)$/
+
+    let mockCamp
+    let mockHandleRequest
 
     beforeEach(() => {
       mockCamp = {
         route: sinon.spy(),
-      };
-      mockHandleRequest = sinon.spy();
-      DummyService.register(mockCamp, mockHandleRequest, defaultConfig);
-    });
+      }
+      mockHandleRequest = sinon.spy()
+      DummyService.register(mockCamp, mockHandleRequest, defaultConfig)
+    })
 
     it('registers the service', () => {
-      expect(mockCamp.route).to.have.been.calledOnce;
-      expect(mockCamp.route).to.have.been.calledWith(expectedRouteRegex);
-    });
+      expect(mockCamp.route).to.have.been.calledOnce
+      expect(mockCamp.route).to.have.been.calledWith(expectedRouteRegex)
+    })
 
     it('handles the request', async () => {
-      expect(mockHandleRequest).to.have.been.calledOnce;
-      const { handler: requestHandler } = mockHandleRequest.getCall(0).args[0];
+      expect(mockHandleRequest).to.have.been.calledOnce
+      const { handler: requestHandler } = mockHandleRequest.getCall(0).args[0]
 
-      const mockSendBadge = sinon.spy();
+      const mockSendBadge = sinon.spy()
       const mockRequest = {
         asPromise: sinon.spy(),
-      };
-      const queryParams = { queryParamA: '?' };
-      const match = '/foo/bar.svg'.match(expectedRouteRegex);
-      await requestHandler(queryParams, match, mockSendBadge, mockRequest);
-
-      const expectedFormat = 'svg';
-      expect(mockSendBadge).to.have.been.calledOnce;
-      expect(mockSendBadge).to.have.been.calledWith(
-        expectedFormat,
-        {
-          text: ['cat', 'Hello bar?'],
-          colorscheme: 'lightgrey',
-          template: undefined,
-          logo: undefined,
-          logoWidth: NaN,
-          links: [],
-          colorA: undefined,
-        }
-      );
-    });
-  });
+      }
+      const queryParams = { queryParamA: '?' }
+      const match = '/foo/bar.svg'.match(expectedRouteRegex)
+      await requestHandler(queryParams, match, mockSendBadge, mockRequest)
+
+      const expectedFormat = 'svg'
+      expect(mockSendBadge).to.have.been.calledOnce
+      expect(mockSendBadge).to.have.been.calledWith(expectedFormat, {
+        text: ['cat', 'Hello bar?'],
+        colorscheme: 'lightgrey',
+        template: undefined,
+        logo: undefined,
+        logoWidth: NaN,
+        links: [],
+        colorA: undefined,
+      })
+    })
+  })
 
   describe('prepareExamples', function() {
     it('returns the expected result', function() {
-      const [first, second] = DummyService.prepareExamples();
+      const [first, second] = DummyService.prepareExamples()
       expect(first).to.deep.equal({
         title: 'DummyService',
         previewUri: '/foo/World.svg',
         exampleUri: undefined,
         documentation: undefined,
-      });
+      })
       expect(second).to.deep.equal({
         title: 'DummyService',
         previewUri: '/foo/World.svg?queryParamA=%21%21%21',
         exampleUri: undefined,
         documentation: undefined,
-      });
-    });
-  });
-});
+      })
+    })
+  })
+})
diff --git a/services/bitbucket/bitbucket.tester.js b/services/bitbucket/bitbucket.tester.js
index 90553f20aa31809031229623459a7a3a037f2fcf..9cdf09a2b37b8e6204e71ae86b1a8c3f9c2648ed 100644
--- a/services/bitbucket/bitbucket.tester.js
+++ b/services/bitbucket/bitbucket.tester.js
@@ -1,140 +1,151 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isBuildStatus,
   isMetric,
-  isMetricOpenIssues
-} = require('../test-validators');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'bitbucket', title: 'Bitbucket badges' });
-module.exports = t;
+  isMetricOpenIssues,
+} = require('../test-validators')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'bitbucket', title: 'Bitbucket badges' })
+module.exports = t
 
 // tests for issues endpoints
 
 t.create('issues-raw (valid)')
   .get('/issues-raw/atlassian/python-bitbucket.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'issues',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'issues',
+      value: isMetric,
+    })
+  )
 
 t.create('issues-raw (not found)')
   .get('/issues-raw/atlassian/not-a-repo.json')
-  .expectJSON({ name: 'issues', value: 'not found' });
+  .expectJSON({ name: 'issues', value: 'not found' })
 
 t.create('issues-raw (invalid)')
   .get('/issues-raw/chris48s/example-private-repo.json')
-  .expectJSON({ name: 'issues', value: 'invalid' });
+  .expectJSON({ name: 'issues', value: 'invalid' })
 
 t.create('issues-raw (connection error)')
   .get('/issues-raw/atlassian/python-bitbucket.json')
   .networkOff()
-  .expectJSON({ name: 'issues', value: 'inaccessible' });
+  .expectJSON({ name: 'issues', value: 'inaccessible' })
 
 t.create('issues (valid)')
   .get('/issues/atlassian/python-bitbucket.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'issues',
-    value: isMetricOpenIssues
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'issues',
+      value: isMetricOpenIssues,
+    })
+  )
 
 t.create('issues (not found)')
   .get('/issues/atlassian/not-a-repo.json')
-  .expectJSON({ name: 'issues', value: 'not found' });
+  .expectJSON({ name: 'issues', value: 'not found' })
 
 t.create('issues (invalid)')
   .get('/issues/chris48s/example-private-repo.json')
-  .expectJSON({ name: 'issues', value: 'invalid' });
+  .expectJSON({ name: 'issues', value: 'invalid' })
 
 t.create('issues (connection error)')
   .get('/issues/atlassian/python-bitbucket.json')
   .networkOff()
-  .expectJSON({ name: 'issues', value: 'inaccessible' });
-
+  .expectJSON({ name: 'issues', value: 'inaccessible' })
 
 // tests for pull requests endpoints
 
 t.create('pr-raw (valid)')
   .get('/pr-raw/atlassian/python-bitbucket.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'pull requests',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'pull requests',
+      value: isMetric,
+    })
+  )
 
 t.create('pr-raw (not found)')
   .get('/pr-raw/atlassian/not-a-repo.json')
-  .expectJSON({ name: 'pull requests', value: 'not found' });
+  .expectJSON({ name: 'pull requests', value: 'not found' })
 
 t.create('pr-raw (invalid)')
   .get('/pr-raw/chris48s/example-private-repo.json')
-  .expectJSON({ name: 'pull requests', value: 'invalid' });
+  .expectJSON({ name: 'pull requests', value: 'invalid' })
 
 t.create('pr-raw (connection error)')
   .get('/pr-raw/atlassian/python-bitbucket.json')
   .networkOff()
-  .expectJSON({ name: 'pull requests', value: 'inaccessible' });
+  .expectJSON({ name: 'pull requests', value: 'inaccessible' })
 
 t.create('pr (valid)')
   .get('/pr/atlassian/python-bitbucket.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'pull requests',
-    value: isMetricOpenIssues
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'pull requests',
+      value: isMetricOpenIssues,
+    })
+  )
 
 t.create('pr (not found)')
   .get('/pr/atlassian/not-a-repo.json')
-  .expectJSON({ name: 'pull requests', value: 'not found' });
+  .expectJSON({ name: 'pull requests', value: 'not found' })
 
 t.create('pr (invalid)')
   .get('/pr/chris48s/example-private-repo.json')
-  .expectJSON({ name: 'pull requests', value: 'invalid' });
+  .expectJSON({ name: 'pull requests', value: 'invalid' })
 
 t.create('pr (connection error)')
   .get('/pr/atlassian/python-bitbucket.json')
   .networkOff()
-  .expectJSON({ name: 'pull requests', value: 'inaccessible' });
-
+  .expectJSON({ name: 'pull requests', value: 'inaccessible' })
 
 // tests for Bitbucket Pipelines
 
 function bitbucketApiResponse(status) {
   return JSON.stringify({
-    "values": [
+    values: [
       {
-        "state": {
-          "type": "pipeline_state_completed",
-          "name": "COMPLETED",
-          "result": {
-            "type": "pipeline_state_completed_xyz",
-            "name": status
-          }
-        }
-      }
-    ]
-  });
+        state: {
+          type: 'pipeline_state_completed',
+          name: 'COMPLETED',
+          result: {
+            type: 'pipeline_state_completed_xyz',
+            name: status,
+          },
+        },
+      },
+    ],
+  })
 }
 
 t.create('master build result (valid)')
   .get('/pipelines/atlassian/adf-builder-javascript.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: isBuildStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: isBuildStatus,
+    })
+  )
 
 t.create('master build result (not found)')
   .get('/pipelines/atlassian/not-a-repo.json')
   .expectJSON({ name: 'build', value: 'not found' })
 
 t.create('branch build result (valid)')
-  .get('/pipelines/atlassian/adf-builder-javascript/shields-test-dont-remove.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: isBuildStatus
-  }));
+  .get(
+    '/pipelines/atlassian/adf-builder-javascript/shields-test-dont-remove.json'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: isBuildStatus,
+    })
+  )
 
 t.create('branch build result (not found)')
   .get('/pipelines/atlassian/not-a-repo/some-branch.json')
@@ -146,69 +157,77 @@ t.create('branch build result (never built)')
 
 t.create('build result (passing)')
   .get('/pipelines/atlassian/adf-builder-javascript.json')
-  .intercept(nock => nock('https://api.bitbucket.org')
-    .get(/^\/2.0\/.*/)
-    .reply(200, bitbucketApiResponse('SUCCESSFUL'))
+  .intercept(nock =>
+    nock('https://api.bitbucket.org')
+      .get(/^\/2.0\/.*/)
+      .reply(200, bitbucketApiResponse('SUCCESSFUL'))
   )
   .expectJSON({ name: 'build', value: 'passing' })
 
 t.create('build result (failing)')
   .get('/pipelines/atlassian/adf-builder-javascript.json')
-  .intercept(nock => nock('https://api.bitbucket.org')
-    .get(/^\/2.0\/.*/)
-    .reply(200, bitbucketApiResponse('FAILED'))
+  .intercept(nock =>
+    nock('https://api.bitbucket.org')
+      .get(/^\/2.0\/.*/)
+      .reply(200, bitbucketApiResponse('FAILED'))
   )
   .expectJSON({ name: 'build', value: 'failing' })
 
 t.create('build result (error)')
   .get('/pipelines/atlassian/adf-builder-javascript.json')
-  .intercept(nock => nock('https://api.bitbucket.org')
-    .get(/^\/2.0\/.*/)
-    .reply(200, bitbucketApiResponse('ERROR'))
+  .intercept(nock =>
+    nock('https://api.bitbucket.org')
+      .get(/^\/2.0\/.*/)
+      .reply(200, bitbucketApiResponse('ERROR'))
   )
   .expectJSON({ name: 'build', value: 'error' })
 
 t.create('build result (stopped)')
   .get('/pipelines/atlassian/adf-builder-javascript.json')
-  .intercept(nock => nock('https://api.bitbucket.org')
-    .get(/^\/2.0\/.*/)
-    .reply(200, bitbucketApiResponse('STOPPED'))
+  .intercept(nock =>
+    nock('https://api.bitbucket.org')
+      .get(/^\/2.0\/.*/)
+      .reply(200, bitbucketApiResponse('STOPPED'))
   )
   .expectJSON({ name: 'build', value: 'stopped' })
 
 t.create('build result (expired)')
   .get('/pipelines/atlassian/adf-builder-javascript.json')
-  .intercept(nock => nock('https://api.bitbucket.org')
-    .get(/^\/2.0\/.*/)
-    .reply(200, bitbucketApiResponse('EXPIRED'))
+  .intercept(nock =>
+    nock('https://api.bitbucket.org')
+      .get(/^\/2.0\/.*/)
+      .reply(200, bitbucketApiResponse('EXPIRED'))
   )
   .expectJSON({ name: 'build', value: 'expired' })
 
 t.create('build result (unknown)')
   .get('/pipelines/atlassian/adf-builder-javascript.json')
-  .intercept(nock => nock('https://api.bitbucket.org')
-    .get(/^\/2.0\/.*/)
-    .reply(200, bitbucketApiResponse('NEW_AND_UNEXPECTED'))
+  .intercept(nock =>
+    nock('https://api.bitbucket.org')
+      .get(/^\/2.0\/.*/)
+      .reply(200, bitbucketApiResponse('NEW_AND_UNEXPECTED'))
   )
   .expectJSON({ name: 'build', value: 'unknown' })
 
 t.create('build result (empty json)')
   .get('/pipelines/atlassian/adf-builder-javascript.json')
-  .intercept(nock => nock('https://api.bitbucket.org')
-    .get(/^\/2.0\/.*/)
-    .reply(200, '{}')
+  .intercept(nock =>
+    nock('https://api.bitbucket.org')
+      .get(/^\/2.0\/.*/)
+      .reply(200, '{}')
   )
   .expectJSON({ name: 'build', value: 'invalid' })
 
 t.create('build result (invalid json)')
   .get('/pipelines/atlassian/adf-builder-javascript.json')
-  .intercept(nock => nock('https://api.bitbucket.org')
-    .get(/^\/2.0\/.*/)
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.bitbucket.org')
+      .get(/^\/2.0\/.*/)
+      .reply(invalidJSON)
   )
   .expectJSON({ name: 'build', value: 'invalid' })
 
 t.create('build result (network error)')
   .get('/pipelines/atlassian/adf-builder-javascript.json')
   .networkOff()
-  .expectJSON({ name: 'build', value: 'inaccessible' });
+  .expectJSON({ name: 'build', value: 'inaccessible' })
diff --git a/services/bithound/bithound.tester.js b/services/bithound/bithound.tester.js
index f2a2840a1bca89824d1148a470caf3486dbfface..13510764d2ae0e0b1d79d8e88c5c432fa28ef379 100644
--- a/services/bithound/bithound.tester.js
+++ b/services/bithound/bithound.tester.js
@@ -1,27 +1,27 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'bithound', title: 'BitHound' });
-module.exports = t;
+const t = new ServiceTester({ id: 'bithound', title: 'BitHound' })
+module.exports = t
 
 t.create('no longer available (code)')
   .get('/code/github/rexxars/sse-channel.json')
   .expectJSON({
     name: 'bithound',
-    value: 'no longer available'
-  });
+    value: 'no longer available',
+  })
 
 t.create('no longer available (dependencies)')
   .get('/dependencies/github/rexxars/sse-channel.json')
   .expectJSON({
     name: 'bithound',
-    value: 'no longer available'
-  });
+    value: 'no longer available',
+  })
 
 t.create('no longer available (devDpendencies)')
   .get('/devDependencies/github/rexxars/sse-channel.json')
   .expectJSON({
     name: 'bithound',
-    value: 'no longer available'
-  });
+    value: 'no longer available',
+  })
diff --git a/services/bitrise/bitrise.tester.js b/services/bitrise/bitrise.tester.js
index 5c47e89c73f30d2b908b5ad5052b491c4e2d1099..e688630f808c1663988fe90304eccd6464f822f7 100644
--- a/services/bitrise/bitrise.tester.js
+++ b/services/bitrise/bitrise.tester.js
@@ -1,53 +1,51 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'bitrise', title: 'Bitrise' });
-module.exports = t;
+const t = new ServiceTester({ id: 'bitrise', title: 'Bitrise' })
+module.exports = t
 
 t.create('deploy status')
   .get('/cde737473028420d/master.json?token=GCIdEzacE4GW32jLVrZb7A')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'bitrise',
-    value: Joi.equal(
-      'success',
-      'error',
-      'unknown'
-    )
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'bitrise',
+      value: Joi.equal('success', 'error', 'unknown'),
+    })
+  )
 
 t.create('deploy status without branch')
   .get('/cde737473028420d.json?token=GCIdEzacE4GW32jLVrZb7A')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'bitrise',
-    value: Joi.equal(
-      'success',
-      'error',
-      'unknown'
-    )
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'bitrise',
+      value: Joi.equal('success', 'error', 'unknown'),
+    })
+  )
 
 t.create('unknown branch')
   .get('/cde737473028420d/unknown.json?token=GCIdEzacE4GW32jLVrZb7A')
-  .expectJSON({ name: 'bitrise', value: 'unknown' });
+  .expectJSON({ name: 'bitrise', value: 'unknown' })
 
 t.create('invalid token')
   .get('/cde737473028420d/unknown.json?token=token')
-  .expectJSON({ name: 'bitrise', value: 'inaccessible' });
+  .expectJSON({ name: 'bitrise', value: 'inaccessible' })
 
 t.create('invalid App ID')
   .get('/invalid/master.json?token=GCIdEzacE4GW32jLVrZb7A')
-  .expectJSON({ name: 'bitrise', value: 'inaccessible' });
+  .expectJSON({ name: 'bitrise', value: 'inaccessible' })
 
 t.create('server error')
   .get('/AppID/branch.json?token=token')
-  .intercept(nock => nock('https://app.bitrise.io')
-    .get('/app/AppID/status.json?token=token&branch=branch')
-    .reply(500, 'Something went wrong'))
-  .expectJSON({ name: 'bitrise', value: 'inaccessible' });
+  .intercept(nock =>
+    nock('https://app.bitrise.io')
+      .get('/app/AppID/status.json?token=token&branch=branch')
+      .reply(500, 'Something went wrong')
+  )
+  .expectJSON({ name: 'bitrise', value: 'inaccessible' })
 
 t.create('connection error')
   .get('/AppID/branch.json?token=token')
   .networkOff()
-  .expectJSON({ name: 'bitrise', value: 'inaccessible' });
+  .expectJSON({ name: 'bitrise', value: 'inaccessible' })
diff --git a/services/bountysource/bountysource.tester.js b/services/bountysource/bountysource.tester.js
index f8a83e303d1a75c3ee7cb7d2ce31a4de16c77560..af0b651a913333d45c486e9f1c3c699871f8ae20 100644
--- a/services/bountysource/bountysource.tester.js
+++ b/services/bountysource/bountysource.tester.js
@@ -1,47 +1,52 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'bountysource', title: 'Bountysource' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'bountysource', title: 'Bountysource' })
+module.exports = t
 
 t.create('bounties (valid)')
   .get('/team/mozilla-core/activity.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'bounties',
-    value: Joi.number().integer().positive()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'bounties',
+      value: Joi.number()
+        .integer()
+        .positive(),
+    })
+  )
 
 t.create('bounties (invalid team)')
   .get('/team/not-a-real-team/activity.json')
   .expectJSON({
     name: 'bounties',
-    value: 'not found'
-  });
+    value: 'not found',
+  })
 
 t.create('bounties (connection error)')
   .get('/team/mozilla-core/activity.json')
   .networkOff()
-  .expectJSON({name: 'bounties', value: 'inaccessible'});
+  .expectJSON({ name: 'bounties', value: 'inaccessible' })
 
 t.create('bounties (unexpected response)')
   .get('/team/mozilla-core/activity.json')
-  .intercept(nock => nock('https://api.bountysource.com')
-    .get('/teams/mozilla-core')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.bountysource.com')
+      .get('/teams/mozilla-core')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'bounties', value: 'invalid'});
+  .expectJSON({ name: 'bounties', value: 'invalid' })
 
 t.create('bounties (error response)')
   .get('/team/mozilla-core/activity.json')
-  .intercept(nock => nock('https://api.bountysource.com')
-    .get('/teams/mozilla-core')
-    .reply(500, '{"error":"oh noes!!"}')
+  .intercept(nock =>
+    nock('https://api.bountysource.com')
+      .get('/teams/mozilla-core')
+      .reply(500, '{"error":"oh noes!!"}')
   )
   .expectJSON({
     name: 'bounties',
-    value: 'invalid'
-  });
+    value: 'invalid',
+  })
diff --git a/services/bower/bower.tester.js b/services/bower/bower.tester.js
index 6d720b1a426c5e675721e2482907d21f4215e251..b47238db335c984670f41ea4335f672d39a90e24 100644
--- a/services/bower/bower.tester.js
+++ b/services/bower/bower.tester.js
@@ -1,67 +1,77 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
 
-const isBowerPrereleaseVersion = Joi.string().regex(/^v\d+(\.\d+)?(\.\d+)?(-?[.\w\d])+?$/);
+const isBowerPrereleaseVersion = Joi.string().regex(
+  /^v\d+(\.\d+)?(\.\d+)?(-?[.\w\d])+?$/
+)
 
-const t = new ServiceTester({ id: 'bower', title: 'Bower' });
-module.exports = t;
+const t = new ServiceTester({ id: 'bower', title: 'Bower' })
+module.exports = t
 
 t.create('licence')
   .get('/l/bootstrap.json')
-  .expectJSON({ name: 'bower', value: 'MIT' });
+  .expectJSON({ name: 'bower', value: 'MIT' })
 
 t.create('custom label for licence')
   .get('/l/bootstrap.json?label=my licence')
-  .expectJSON({ name: 'my licence', value: 'MIT' });
+  .expectJSON({ name: 'my licence', value: 'MIT' })
 
 t.create('version')
   .get('/v/bootstrap.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'bower',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'bower',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('custom label for version')
   .get('/v/bootstrap.json?label=my version')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'my version',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'my version',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('pre version') // e.g. bower|v0.2.5-alpha-rc-pre
   .get('/vpre/bootstrap.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'bower',
-    value: isBowerPrereleaseVersion
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'bower',
+      value: isBowerPrereleaseVersion,
+    })
+  )
 
 t.create('custom label for pre version') // e.g. pre version|v0.2.5-alpha-rc-pre
   .get('/vpre/bootstrap.json?label=pre version')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'pre version',
-    value: isBowerPrereleaseVersion
-  }));
-
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'pre version',
+      value: isBowerPrereleaseVersion,
+    })
+  )
 
 t.create('Version for Invaild Package')
   .get('/v/it-is-a-invalid-package-should-error.json')
-  .expectJSON({ name: 'bower', value: 'invalid' });
+  .expectJSON({ name: 'bower', value: 'invalid' })
 
 t.create('Pre Version for Invaild Package')
   .get('/vpre/it-is-a-invalid-package-should-error.json')
-  .expectJSON({ name: 'bower', value: 'invalid' });
+  .expectJSON({ name: 'bower', value: 'invalid' })
 
 t.create('licence for Invaild Package')
   .get('/l/it-is-a-invalid-package-should-error.json')
-  .expectJSON({ name: 'bower', value: 'invalid' });
-
+  .expectJSON({ name: 'bower', value: 'invalid' })
 
 t.create('Version label should be `no releases` if no official version')
   .get('/v/bootstrap.json')
-  .intercept(nock => nock('https://libraries.io')
-    .get('/api/bower/bootstrap')
-    .reply(200, { latest_stable_release: { name: null } })) // or just `{}`
-  .expectJSON({ name: 'bower', value: 'no releases' });
+  .intercept(nock =>
+    nock('https://libraries.io')
+      .get('/api/bower/bootstrap')
+      .reply(200, { latest_stable_release: { name: null } })
+  ) // or just `{}`
+  .expectJSON({ name: 'bower', value: 'no releases' })
diff --git a/services/bugzilla/bugzilla.tester.js b/services/bugzilla/bugzilla.tester.js
index a2abb486d4e8f876f5c3d11bddc23a799caa1458..547ffd0a34c3f95f4b0b5a54b6413c5d3c10488d 100644
--- a/services/bugzilla/bugzilla.tester.js
+++ b/services/bugzilla/bugzilla.tester.js
@@ -1,7 +1,7 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
 const bzBugStatus = Joi.equal(
   'unconfirmed',
@@ -9,27 +9,29 @@ const bzBugStatus = Joi.equal(
   'assigned',
   'fixed',
   'invalid',
-  'won\'t fix',
+  "won't fix",
   'duplicate',
   'works for me',
   'incomplete'
-);
+)
 
-const t = new ServiceTester({ id: 'bugzilla', title: 'Bugzilla' });
-module.exports = t;
+const t = new ServiceTester({ id: 'bugzilla', title: 'Bugzilla' })
+module.exports = t
 
 t.create('Bugzilla valid bug status')
   .get('/996038.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'bug 996038',
-    value: bzBugStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'bug 996038',
+      value: bzBugStatus,
+    })
+  )
 
 t.create('Bugzilla invalid bug status')
   .get('/83548978974387943879.json')
-  .expectJSON({ name: 'bug 83548978974387943879', value: 'not found' });
+  .expectJSON({ name: 'bug 83548978974387943879', value: 'not found' })
 
 t.create('Bugzilla failed request bug status')
   .get('/996038.json')
   .networkOff()
-  .expectJSON({ name: 'bug 996038', value: 'inaccessible' });
+  .expectJSON({ name: 'bug 996038', value: 'inaccessible' })
diff --git a/services/buildkite/buildkite.tester.js b/services/buildkite/buildkite.tester.js
index 8ff31cdd39b4ce0864fca657968b73a4895f5f78..fbc64881b06bcec8a252d5bb876af02cc6788042 100644
--- a/services/buildkite/buildkite.tester.js
+++ b/services/buildkite/buildkite.tester.js
@@ -1,43 +1,52 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const t = new ServiceTester({ id: 'buildkite', title: 'Buildkite Builds' });
-const { invalidJSON } = require('../response-fixtures');
-const { isBuildStatus } = require('../test-validators');
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const t = new ServiceTester({ id: 'buildkite', title: 'Buildkite Builds' })
+const { invalidJSON } = require('../response-fixtures')
+const { isBuildStatus } = require('../test-validators')
+module.exports = t
 
 t.create('buildkite invalid pipeline')
   .get('/unknown-identifier/unknown-branch.json')
-  .expectJSON({ name: 'build', value: 'not found' });
+  .expectJSON({ name: 'build', value: 'not found' })
 
 t.create('buildkite valid pipeline')
   .get('/3826789cf8890b426057e6fe1c4e683bdf04fa24d498885489/master.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown'))
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('buildkite valid pipeline skipping branch')
   .get('/3826789cf8890b426057e6fe1c4e683bdf04fa24d498885489.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown'))
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('buildkite unknown branch')
-  .get('/3826789cf8890b426057e6fe1c4e683bdf04fa24d498885489/unknown-branch.json')
-  .expectJSON({ name: 'build', value: 'unknown' });
+  .get(
+    '/3826789cf8890b426057e6fe1c4e683bdf04fa24d498885489/unknown-branch.json'
+  )
+  .expectJSON({ name: 'build', value: 'unknown' })
 
 t.create('buildkite connection error')
   .get('/_.json')
   .networkOff()
-  .expectJSON({ name: 'build', value: 'inaccessible' });
+  .expectJSON({ name: 'build', value: 'inaccessible' })
 
 t.create('buildkite unexpected response')
   .get('/3826789cf8890b426057e6fe1c4e683bdf04fa24d498885489.json')
-  .intercept(nock => nock('https://badge.buildkite.com')
-    .get('/3826789cf8890b426057e6fe1c4e683bdf04fa24d498885489.json?branch=master')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://badge.buildkite.com')
+      .get(
+        '/3826789cf8890b426057e6fe1c4e683bdf04fa24d498885489.json?branch=master'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'build', value: 'invalid'});
+  .expectJSON({ name: 'build', value: 'invalid' })
diff --git a/services/bundlephobia/bundlephobia.tester.js b/services/bundlephobia/bundlephobia.tester.js
index f72561e1772feccc17ed2a8af11dec36a71c25e9..e0548943480ebc40cd3ec57dc6173748e535fd82 100644
--- a/services/bundlephobia/bundlephobia.tester.js
+++ b/services/bundlephobia/bundlephobia.tester.js
@@ -5,7 +5,8 @@ const ServiceTester = require('../service-tester')
 const { isFileSize } = require('../test-validators')
 
 const t = new ServiceTester({
-  id: 'bundlephobia', title: 'NPM package bundle size',
+  id: 'bundlephobia',
+  title: 'NPM package bundle size',
 })
 
 module.exports = t
@@ -67,12 +68,11 @@ const data = [
     format: formats.C,
     get: '/min/@some-no-exist/some-no-exist.json',
     expect: { name: 'minified size', value: 'package not found error' },
-  }
+  },
 ]
 
-data.forEach( ({format, get, expect }) => {
+data.forEach(({ format, get, expect }) => {
   t.create(`Testing format '${format}' against '${get}'`)
     .get(get)
     .expectJSONTypes(Joi.object().keys(expect))
-  }
-)
+})
diff --git a/services/cauditor/cauditor.tester.js b/services/cauditor/cauditor.tester.js
index d2fa3d92e9ba7ec57fdfb4719a105cfda23051c5..84f7bf6d5594f38af6127fe57d01b1531d838243 100644
--- a/services/cauditor/cauditor.tester.js
+++ b/services/cauditor/cauditor.tester.js
@@ -1,9 +1,9 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'cauditor', title: 'Cauditor' });
-module.exports = t;
+const t = new ServiceTester({ id: 'cauditor', title: 'Cauditor' })
+module.exports = t
 
 t.create('no longer available')
   .get('/mi/matthiasmullie/scrapbook/master.json?style=_shields_test')
@@ -11,4 +11,4 @@ t.create('no longer available')
     name: 'cauditor',
     value: 'no longer available',
     colorB: '#9f9f9f',
-  });
\ No newline at end of file
+  })
diff --git a/services/cdnjs/cdnjs.service.js b/services/cdnjs/cdnjs.service.js
index 47f7151d9a11262c94e6cbd440455d36cd45b62c..52861c82754db77d007b2468dedbae15ce89696a 100644
--- a/services/cdnjs/cdnjs.service.js
+++ b/services/cdnjs/cdnjs.service.js
@@ -1,58 +1,55 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const { BaseJsonService } = require('../base');
-const { NotFound } = require('../errors');
-const { addv: versionText } = require('../../lib/text-formatters');
-const { version: versionColor} = require('../../lib/color-formatters');
+const Joi = require('joi')
+const { BaseJsonService } = require('../base')
+const { NotFound } = require('../errors')
+const { addv: versionText } = require('../../lib/text-formatters')
+const { version: versionColor } = require('../../lib/color-formatters')
 
 module.exports = class Cdnjs extends BaseJsonService {
-  async handle({library}) {
-    const url = `https://api.cdnjs.com/libraries/${library}?fields=version`;
+  async handle({ library }) {
+    const url = `https://api.cdnjs.com/libraries/${library}?fields=version`
     const json = await this._requestJson({
       url,
       schema: Joi.any(),
-    });
+    })
 
     if (Object.keys(json).length === 0) {
       /* Note the 'not found' response from cdnjs is:
          status code = 200, body = {} */
-      throw new NotFound();
+      throw new NotFound()
     }
-    const version = json.version || 0;
+    const version = json.version || 0
 
     return {
       message: versionText(version),
-      color: versionColor(version)
-    };
+      color: versionColor(version),
+    }
   }
 
   // Metadata
   static get defaultBadgeData() {
-    return { label: 'cdnjs' };
+    return { label: 'cdnjs' }
   }
 
   static get category() {
-    return 'version';
+    return 'version'
   }
 
   static get url() {
     return {
       base: 'cdnjs/v',
       format: '(.+)',
-      capture: ['library']
-    };
+      capture: ['library'],
+    }
   }
 
   static get examples() {
     return [
       {
         previewUrl: 'jquery',
-        keywords: [
-          'cdn',
-          'cdnjs'
-        ]
-      }
-    ];
+        keywords: ['cdn', 'cdnjs'],
+      },
+    ]
   }
-};
+}
diff --git a/services/cdnjs/cdnjs.tester.js b/services/cdnjs/cdnjs.tester.js
index 1001091809572fa3125aa2c936248e5abc9c7fad..02991999523154b221fdf0cfeccff3813542eb26 100644
--- a/services/cdnjs/cdnjs.tester.js
+++ b/services/cdnjs/cdnjs.tester.js
@@ -1,33 +1,35 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isVPlusTripleDottedVersion } = require('../test-validators');
-
-const t = new ServiceTester({ id: 'cdnjs', title: 'CDNJs' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isVPlusTripleDottedVersion } = require('../test-validators')
 
+const t = new ServiceTester({ id: 'cdnjs', title: 'CDNJs' })
+module.exports = t
 
 t.create('cdnjs (valid)')
   .get('/v/jquery.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'cdnjs',
-    value: isVPlusTripleDottedVersion,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'cdnjs',
+      value: isVPlusTripleDottedVersion,
+    })
+  )
 
 t.create('cdnjs (not found)')
   .get('/v/not-a-library.json')
-  .expectJSON({name: 'cdnjs', value: 'not found'});
+  .expectJSON({ name: 'cdnjs', value: 'not found' })
 
 t.create('cdnjs (connection error)')
   .get('/v/jquery.json')
   .networkOff()
-  .expectJSON({name: 'cdnjs', value: 'inaccessible'});
+  .expectJSON({ name: 'cdnjs', value: 'inaccessible' })
 
 t.create('cdnjs (error response)')
   .get('/v/jquery.json')
-  .intercept(nock => nock('https://api.cdnjs.com')
-    .get('/libraries/jquery?fields=version')
-    .reply(500, '{"error":"oh noes!!"}')
+  .intercept(nock =>
+    nock('https://api.cdnjs.com')
+      .get('/libraries/jquery?fields=version')
+      .reply(500, '{"error":"oh noes!!"}')
   )
-  .expectJSON({name: 'cdnjs', value: 'invalid'});
+  .expectJSON({ name: 'cdnjs', value: 'invalid' })
diff --git a/services/chocolatey/chocolatey.tester.js b/services/chocolatey/chocolatey.tester.js
index c4a01b7b8b6edf8fabe75a403197efdec6eacb6b..591c6710d6d32051cb32d8a2004e9b61e753f8eb 100644
--- a/services/chocolatey/chocolatey.tester.js
+++ b/services/chocolatey/chocolatey.tester.js
@@ -1,172 +1,202 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isMetric,
   isVPlusDottedVersionNClauses,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators');
-const colorscheme = require('../../lib/colorscheme.json');
+} = require('../test-validators')
+const colorscheme = require('../../lib/colorscheme.json')
 const {
   nuGetV2VersionJsonWithDash,
   nuGetV2VersionJsonFirstCharZero,
-  nuGetV2VersionJsonFirstCharNotZero
-} = require('../nuget-fixtures');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'chocolatey', title: 'Chocolatey' });
-module.exports = t;
+  nuGetV2VersionJsonFirstCharNotZero,
+} = require('../nuget-fixtures')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'chocolatey', title: 'Chocolatey' })
+module.exports = t
 
 // downloads
 
 t.create('total downloads (valid)')
   .get('/dt/scriptcs.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('total downloads (not found)')
   .get('/dt/not-a-real-package.json')
-  .expectJSON({name: 'downloads', value: 'not found'});
+  .expectJSON({ name: 'downloads', value: 'not found' })
 
 t.create('total downloads (connection error)')
   .get('/dt/scriptcs.json')
   .networkOff()
-  .expectJSON({name: 'downloads', value: 'inaccessible'});
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 t.create('total downloads (unexpected response)')
   .get('/dt/scriptcs.json')
-  .intercept(nock => nock('https://www.chocolatey.org')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://www.chocolatey.org')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'downloads', value: 'invalid'});
-
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 // version
 
 t.create('version (valid)')
   .get('/v/scriptcs.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'chocolatey',
-    value: isVPlusDottedVersionNClauses,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'chocolatey',
+      value: isVPlusDottedVersionNClauses,
+    })
+  )
 
 t.create('version (mocked, yellow badge)')
   .get('/v/scriptcs.json?style=_shields_test')
-  .intercept(nock => nock('https://www.chocolatey.org')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonWithDash)
+  .intercept(nock =>
+    nock('https://www.chocolatey.org')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonWithDash)
   )
   .expectJSON({
     name: 'chocolatey',
     value: 'v1.2-beta',
-    colorB: colorscheme.yellow.colorB
-  });
+    colorB: colorscheme.yellow.colorB,
+  })
 
 t.create('version (mocked, orange badge)')
   .get('/v/scriptcs.json?style=_shields_test')
-  .intercept(nock => nock('https://www.chocolatey.org')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharZero)
+  .intercept(nock =>
+    nock('https://www.chocolatey.org')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharZero)
   )
   .expectJSON({
     name: 'chocolatey',
     value: 'v0.35',
-    colorB: colorscheme.orange.colorB
-  });
+    colorB: colorscheme.orange.colorB,
+  })
 
 t.create('version (mocked, blue badge)')
   .get('/v/scriptcs.json?style=_shields_test')
-  .intercept(nock => nock('https://www.chocolatey.org')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharNotZero)
+  .intercept(nock =>
+    nock('https://www.chocolatey.org')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharNotZero)
   )
   .expectJSON({
     name: 'chocolatey',
     value: 'v1.2.7',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('version (not found)')
   .get('/v/not-a-real-package.json')
-  .expectJSON({name: 'chocolatey', value: 'not found'});
+  .expectJSON({ name: 'chocolatey', value: 'not found' })
 
 t.create('version (connection error)')
   .get('/v/scriptcs.json')
   .networkOff()
-  .expectJSON({name: 'chocolatey', value: 'inaccessible'});
+  .expectJSON({ name: 'chocolatey', value: 'inaccessible' })
 
 t.create('version (unexpected response)')
   .get('/v/scriptcs.json')
-  .intercept(nock => nock('https://www.chocolatey.org')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://www.chocolatey.org')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'chocolatey', value: 'invalid'});
-
+  .expectJSON({ name: 'chocolatey', value: 'invalid' })
 
 // version (pre)
 
 t.create('version (pre) (valid)')
   .get('/vpre/scriptcs.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'chocolatey',
-    value: isVPlusDottedVersionNClausesWithOptionalSuffix,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'chocolatey',
+      value: isVPlusDottedVersionNClausesWithOptionalSuffix,
+    })
+  )
 
 t.create('version (pre) (mocked, yellow badge)')
   .get('/vpre/scriptcs.json?style=_shields_test')
-  .intercept(nock => nock('https://www.chocolatey.org')
-  .get("/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonWithDash)
+  .intercept(nock =>
+    nock('https://www.chocolatey.org')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonWithDash)
   )
   .expectJSON({
     name: 'chocolatey',
     value: 'v1.2-beta',
-    colorB: colorscheme.yellow.colorB
-  });
+    colorB: colorscheme.yellow.colorB,
+  })
 
 t.create('version (pre) (mocked, orange badge)')
   .get('/vpre/scriptcs.json?style=_shields_test')
-  .intercept(nock => nock('https://www.chocolatey.org')
-  .get("/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharZero)
+  .intercept(nock =>
+    nock('https://www.chocolatey.org')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharZero)
   )
   .expectJSON({
     name: 'chocolatey',
     value: 'v0.35',
-    colorB: colorscheme.orange.colorB
-  });
+    colorB: colorscheme.orange.colorB,
+  })
 
 t.create('version (pre) (mocked, blue badge)')
   .get('/vpre/scriptcs.json?style=_shields_test')
-  .intercept(nock => nock('https://www.chocolatey.org')
-  .get("/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharNotZero)
+  .intercept(nock =>
+    nock('https://www.chocolatey.org')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharNotZero)
   )
   .expectJSON({
     name: 'chocolatey',
     value: 'v1.2.7',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('version (pre) (not found)')
   .get('/vpre/not-a-real-package.json')
-  .expectJSON({name: 'chocolatey', value: 'not found'});
+  .expectJSON({ name: 'chocolatey', value: 'not found' })
 
 t.create('version (pre) (connection error)')
   .get('/vpre/scriptcs.json')
   .networkOff()
-  .expectJSON({name: 'chocolatey', value: 'inaccessible'});
+  .expectJSON({ name: 'chocolatey', value: 'inaccessible' })
 
 t.create('version (pre) (unexpected response)')
   .get('/vpre/scriptcs.json')
-  .intercept(nock => nock('https://www.chocolatey.org')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://www.chocolatey.org')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27scriptcs%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'chocolatey', value: 'invalid'});
+  .expectJSON({ name: 'chocolatey', value: 'invalid' })
diff --git a/services/chrome-web-store/chrome-web-store.tester.js b/services/chrome-web-store/chrome-web-store.tester.js
index 4c35557c680d0a8e4b104fa55dd7895ccbae863d..12053a48c413293d754aa42b0bd90585c1810da0 100644
--- a/services/chrome-web-store/chrome-web-store.tester.js
+++ b/services/chrome-web-store/chrome-web-store.tester.js
@@ -1,55 +1,64 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
 const {
   isVPlusDottedVersionAtLeastOne,
   isStarRating,
-  isMetric
-} = require('../test-validators');
+  isMetric,
+} = require('../test-validators')
 
-const t = new ServiceTester({ id: 'chrome-web-store', title: 'Chrome Web Store' });
-module.exports = t;
+const t = new ServiceTester({
+  id: 'chrome-web-store',
+  title: 'Chrome Web Store',
+})
+module.exports = t
 
 t.create('Downloads (now users)')
   .get('/d/alhjnofcnnpeaphgeakdhkebafjcpeae.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'users', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'users', value: isMetric }))
 
 t.create('Users')
   .get('/users/alhjnofcnnpeaphgeakdhkebafjcpeae.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'users', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'users', value: isMetric }))
 
 t.create('Version')
   .get('/v/alhjnofcnnpeaphgeakdhkebafjcpeae.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'chrome web store',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'chrome web store',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('Version - Custom label')
   .get('/v/alhjnofcnnpeaphgeakdhkebafjcpeae.json?label=IndieGala Helper')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'IndieGala Helper',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'IndieGala Helper',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('Rating')
   .get('/rating/alhjnofcnnpeaphgeakdhkebafjcpeae.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'rating',
-    value: Joi.string().regex(/^\d\.?\d+?\/5$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rating',
+      value: Joi.string().regex(/^\d\.?\d+?\/5$/),
+    })
+  )
 
 t.create('Stars')
   .get('/stars/alhjnofcnnpeaphgeakdhkebafjcpeae.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'rating', value: isStarRating }));
+  .expectJSONTypes(Joi.object().keys({ name: 'rating', value: isStarRating }))
 
 t.create('Invalid addon')
   .get('/d/invalid-name-of-addon.json')
-  .expectJSON({ name: 'chrome web store', value: 'invalid' });
+  .expectJSON({ name: 'chrome web store', value: 'invalid' })
 
 t.create('No connection')
   .get('/v/alhjnofcnnpeaphgeakdhkebafjcpeae.json')
   .networkOff()
-  .expectJSON({ name: 'chrome web store', value: 'inaccessible' });
+  .expectJSON({ name: 'chrome web store', value: 'inaccessible' })
diff --git a/services/circleci/circleci.tester.js b/services/circleci/circleci.tester.js
index 5347c0bc2fb578bfe09431bc24d32c1bc5b1dccb..0a7c01dd7aaf679e3efe9c80c514edd381b16a79 100644
--- a/services/circleci/circleci.tester.js
+++ b/services/circleci/circleci.tester.js
@@ -1,71 +1,80 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
-const { isBuildStatus } = require('../test-validators');
-
-const t = new ServiceTester({ id: 'circleci', title: 'Circle CI' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
+const { isBuildStatus } = require('../test-validators')
 
+const t = new ServiceTester({ id: 'circleci', title: 'Circle CI' })
+module.exports = t
 
 t.create('circle ci (valid, without branch)')
   .get('/project/github/RedSparr0w/node-csgo-parser.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: isBuildStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: isBuildStatus,
+    })
+  )
 
 t.create('circle ci (valid, with branch)')
   .get('/project/github/RedSparr0w/node-csgo-parser/master.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: isBuildStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: isBuildStatus,
+    })
+  )
 
 t.create('circle ci (not found)')
   .get('/project/github/PyvesB/EmptyRepo.json')
-  .expectJSON({name: 'build', value: 'project not found'});
+  .expectJSON({ name: 'build', value: 'project not found' })
 
 t.create('circle ci (connection error)')
   .get('/project/github/RedSparr0w/node-csgo-parser.json')
   .networkOff()
-  .expectJSON({name: 'build', value: 'inaccessible'});
+  .expectJSON({ name: 'build', value: 'inaccessible' })
 
 t.create('circle ci (unexpected response)')
   .get('/project/github/RedSparr0w/node-csgo-parser.json')
-  .intercept(nock => nock('https://circleci.com')
-    .get('/api/v1.1/project/github/RedSparr0w/node-csgo-parser?filter=completed&limit=1')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://circleci.com')
+      .get(
+        '/api/v1.1/project/github/RedSparr0w/node-csgo-parser?filter=completed&limit=1'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'build', value: 'invalid'});
+  .expectJSON({ name: 'build', value: 'invalid' })
 
 t.create('circle ci (no response data)')
   .get('/project/github/RedSparr0w/node-csgo-parser.json')
-  .intercept(nock => nock('https://circleci.com')
-    .get('/api/v1.1/project/github/RedSparr0w/node-csgo-parser?filter=completed&limit=1')
-    .reply(200)
+  .intercept(nock =>
+    nock('https://circleci.com')
+      .get(
+        '/api/v1.1/project/github/RedSparr0w/node-csgo-parser?filter=completed&limit=1'
+      )
+      .reply(200)
   )
-  .expectJSON({ name: 'build', value: 'invalid' });
+  .expectJSON({ name: 'build', value: 'invalid' })
 
 t.create('circle ci (multiple pipelines, pass)')
   .get('/project/github/RedSparr0w/node-csgo-parser.json?style=_shields_test')
-  .intercept(nock => nock('https://circleci.com')
-    .get('/api/v1.1/project/github/RedSparr0w/node-csgo-parser?filter=completed&limit=1')
-    .reply(200, [
-      {'status': 'success'},
-      {'status': 'fixed'}
-    ])
+  .intercept(nock =>
+    nock('https://circleci.com')
+      .get(
+        '/api/v1.1/project/github/RedSparr0w/node-csgo-parser?filter=completed&limit=1'
+      )
+      .reply(200, [{ status: 'success' }, { status: 'fixed' }])
   )
-  .expectJSON({ name: 'build', value: 'passing', colorB: '#4c1', });
+  .expectJSON({ name: 'build', value: 'passing', colorB: '#4c1' })
 
 t.create('circle ci (multiple pipelines, fail)')
   .get('/project/github/RedSparr0w/node-csgo-parser.json?style=_shields_test')
-  .intercept(nock => nock('https://circleci.com')
-    .get('/api/v1.1/project/github/RedSparr0w/node-csgo-parser?filter=completed&limit=1')
-    .reply(200, [
-      {'status': 'success'},
-      {'status': 'failed'}
-    ])
+  .intercept(nock =>
+    nock('https://circleci.com')
+      .get(
+        '/api/v1.1/project/github/RedSparr0w/node-csgo-parser?filter=completed&limit=1'
+      )
+      .reply(200, [{ status: 'success' }, { status: 'failed' }])
   )
-  .expectJSON({ name: 'build', value: 'failed', colorB: '#e05d44', });
+  .expectJSON({ name: 'build', value: 'failed', colorB: '#e05d44' })
diff --git a/services/clojars/clojars.service.js b/services/clojars/clojars.service.js
index 306e7106670a5fa39bc8d202651d3acf1d0e6353..a02509b7277011235ad63054aa0d8541d4fb5083 100644
--- a/services/clojars/clojars.service.js
+++ b/services/clojars/clojars.service.js
@@ -1,51 +1,48 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const { BaseJsonService } = require('../base');
-const { NotFound } = require('../errors');
-const { version: versionColor } = require('../../lib/color-formatters');
+const Joi = require('joi')
+const { BaseJsonService } = require('../base')
+const { NotFound } = require('../errors')
+const { version: versionColor } = require('../../lib/color-formatters')
 
 module.exports = class Clojars extends BaseJsonService {
-  async handle({clojar}) {
-    const url = `https://clojars.org/${clojar}/latest-version.json`;
+  async handle({ clojar }) {
+    const url = `https://clojars.org/${clojar}/latest-version.json`
     const json = await this._requestJson({
       url,
       schema: Joi.any(),
-    });
+    })
 
     if (Object.keys(json).length === 0) {
       /* Note the 'not found' response from clojars is:
           status code = 200, body = {} */
-      throw new NotFound();
+      throw new NotFound()
     }
 
     return {
-      message: "[" + clojar + " \"" + json.version + "\"]",
-      color: versionColor(json.version)
-    };
+      message: '[' + clojar + ' "' + json.version + '"]',
+      color: versionColor(json.version),
+    }
   }
 
   // Metadata
   static get defaultBadgeData() {
-    return { label: 'clojars' };
+    return { label: 'clojars' }
   }
 
   static get category() {
-    return 'version';
+    return 'version'
   }
 
   static get url() {
     return {
       base: 'clojars/v',
       format: '(.+)',
-      capture: ['clojar']
-    };
+      capture: ['clojar'],
+    }
   }
 
   static get examples() {
-    return [
-      { previewUrl: 'prismic' }
-    ];
+    return [{ previewUrl: 'prismic' }]
   }
-
-};
+}
diff --git a/services/clojars/clojars.tester.js b/services/clojars/clojars.tester.js
index fd4199c16f4bf56525cdf4e6bbf365258d0f902f..cf91fee04a9623a55a148270beda87a8393cf196 100644
--- a/services/clojars/clojars.tester.js
+++ b/services/clojars/clojars.tester.js
@@ -1,32 +1,34 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-
-const t = new ServiceTester({ id: 'clojars', title: 'clojars' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
+const t = new ServiceTester({ id: 'clojars', title: 'clojars' })
+module.exports = t
 
 t.create('clojars (valid)')
   .get('/v/prismic.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'clojars',
-    value: /^\[prismic "([0-9][.]?)+"\]$/,  // note: https://github.com/badges/shields/pull/431
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'clojars',
+      value: /^\[prismic "([0-9][.]?)+"\]$/, // note: https://github.com/badges/shields/pull/431
+    })
+  )
 
 t.create('clojars (not found)')
   .get('/v/not-a-package.json')
-  .expectJSON({name: 'clojars', value: 'not found'});
+  .expectJSON({ name: 'clojars', value: 'not found' })
 
 t.create('clojars (connection error)')
   .get('/v/jquery.json')
   .networkOff()
-  .expectJSON({name: 'clojars', value: 'inaccessible'});
+  .expectJSON({ name: 'clojars', value: 'inaccessible' })
 
 t.create('clojars (error response)')
   .get('/v/prismic.json')
-  .intercept(nock => nock('https://clojars.org')
-    .get('/prismic/latest-version.json')
-    .reply(500, '{"error":"oh noes!!"}')
+  .intercept(nock =>
+    nock('https://clojars.org')
+      .get('/prismic/latest-version.json')
+      .reply(500, '{"error":"oh noes!!"}')
   )
-  .expectJSON({name: 'clojars', value: 'invalid'});
+  .expectJSON({ name: 'clojars', value: 'invalid' })
diff --git a/services/cocoapods/cocoapods.tester.js b/services/cocoapods/cocoapods.tester.js
index 2a6dd99685e17dc4f19c5097c128c95f26215b37..143e422f3b16f4b0ab7db2ff79050d0ada23e9cb 100644
--- a/services/cocoapods/cocoapods.tester.js
+++ b/services/cocoapods/cocoapods.tester.js
@@ -1,211 +1,228 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
 const {
-    isIntegerPercentage,
-    isVPlusDottedVersionAtLeastOne,
-} = require('../test-validators');
+  isIntegerPercentage,
+  isVPlusDottedVersionAtLeastOne,
+} = require('../test-validators')
 
-const isPlatform = Joi.string().regex(/^(osx|ios|tvos|watchos)( \| (osx|ios|tvos|watchos))*$/);
+const isPlatform = Joi.string().regex(
+  /^(osx|ios|tvos|watchos)( \| (osx|ios|tvos|watchos))*$/
+)
 
 // these are deliberately not isMetricOverTimePeriod due to
 // https://github.com/CocoaPods/cocoapods.org/issues/348
-const isMetricOverTimePeriodAllowZero = Joi
-  .string()
-  .regex(/^(0|[1-9][0-9]*)[kMGTPEZY]?\/(year|month|4 weeks|week|day)$/);
-const isMetricAllowZero = Joi
-  .string()
-  .regex(/^(0|[1-9][0-9]*)[kMGTPEZY]?$/);
-
-const t = new ServiceTester({ id: 'cocoapods', title: 'Cocoa Pods' });
-module.exports = t;
+const isMetricOverTimePeriodAllowZero = Joi.string().regex(
+  /^(0|[1-9][0-9]*)[kMGTPEZY]?\/(year|month|4 weeks|week|day)$/
+)
+const isMetricAllowZero = Joi.string().regex(/^(0|[1-9][0-9]*)[kMGTPEZY]?$/)
 
+const t = new ServiceTester({ id: 'cocoapods', title: 'Cocoa Pods' })
+module.exports = t
 
 // version endpoint
 
 t.create('version (valid)')
   .get('/v/AFNetworking.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'pod',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'pod',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('version (not found)')
   .get('/v/not-a-package.json')
-  .expectJSON({name: 'pod', value: 'not found'});
+  .expectJSON({ name: 'pod', value: 'not found' })
 
 t.create('version (connection error)')
   .get('/v/AFNetworking.json')
   .networkOff()
-  .expectJSON({name: 'pod', value: 'inaccessible'});
+  .expectJSON({ name: 'pod', value: 'inaccessible' })
 
 t.create('version (unexpected response)')
   .get('/v/AFNetworking.json')
-  .intercept(nock => nock('https://trunk.cocoapods.org')
-    .get('/api/v1/pods/AFNetworking/specs/latest')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://trunk.cocoapods.org')
+      .get('/api/v1/pods/AFNetworking/specs/latest')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'pod', value: 'invalid'});
-
+  .expectJSON({ name: 'pod', value: 'invalid' })
 
 // platform endpoint
 
 t.create('platform (valid)')
   .get('/p/AFNetworking.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'platform',
-    value: isPlatform
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'platform',
+      value: isPlatform,
+    })
+  )
 
 t.create('platform (not found)')
   .get('/p/not-a-package.json')
-  .expectJSON({name: 'platform', value: 'not found'});
+  .expectJSON({ name: 'platform', value: 'not found' })
 
 t.create('platform (connection error)')
   .get('/p/AFNetworking.json')
   .networkOff()
-  .expectJSON({name: 'platform', value: 'inaccessible'});
+  .expectJSON({ name: 'platform', value: 'inaccessible' })
 
 t.create('platform (unexpected response)')
   .get('/p/AFNetworking.json')
-  .intercept(nock => nock('https://trunk.cocoapods.org')
-    .get('/api/v1/pods/AFNetworking/specs/latest')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://trunk.cocoapods.org')
+      .get('/api/v1/pods/AFNetworking/specs/latest')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'platform', value: 'invalid'});
-
+  .expectJSON({ name: 'platform', value: 'invalid' })
 
 // license endpoint
 
 t.create('license (valid)')
   .get('/l/AFNetworking.json')
-  .expectJSON({name: 'license', value: 'MIT'});
+  .expectJSON({ name: 'license', value: 'MIT' })
 
 t.create('license (not found)')
   .get('/l/not-a-package.json')
-  .expectJSON({name: 'license', value: 'not found'});
+  .expectJSON({ name: 'license', value: 'not found' })
 
 t.create('license (connection error)')
   .get('/l/AFNetworking.json')
   .networkOff()
-  .expectJSON({name: 'license', value: 'inaccessible'});
+  .expectJSON({ name: 'license', value: 'inaccessible' })
 
 t.create('license (unexpected response)')
   .get('/l/AFNetworking.json')
-  .intercept(nock => nock('https://trunk.cocoapods.org')
-    .get('/api/v1/pods/AFNetworking/specs/latest')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://trunk.cocoapods.org')
+      .get('/api/v1/pods/AFNetworking/specs/latest')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'license', value: 'invalid'});
-
+  .expectJSON({ name: 'license', value: 'invalid' })
 
 // doc percent endpoint
 
 t.create('doc percent (valid)')
   .get('/metrics/doc-percent/AFNetworking.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docs',
-    value: isIntegerPercentage
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docs',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('doc percent (null)')
   .get('/metrics/doc-percent/AFNetworking.json')
-  .intercept(nock => nock('https://metrics.cocoapods.org')
-    .get('/api/v1/pods/AFNetworking')
-    .reply(200, '{"cocoadocs": {"doc_percent": null}}')
+  .intercept(nock =>
+    nock('https://metrics.cocoapods.org')
+      .get('/api/v1/pods/AFNetworking')
+      .reply(200, '{"cocoadocs": {"doc_percent": null}}')
   )
-  .expectJSON({name: 'docs', value: '0%'});;
+  .expectJSON({ name: 'docs', value: '0%' })
 
 t.create('doc percent (not found)')
   .get('/metrics/doc-percent/not-a-package.json')
-  .expectJSON({name: 'docs', value: 'not found'});
+  .expectJSON({ name: 'docs', value: 'not found' })
 
 t.create('doc percent (connection error)')
   .get('/metrics/doc-percent/AFNetworking.json')
   .networkOff()
-  .expectJSON({name: 'docs', value: 'inaccessible'});
+  .expectJSON({ name: 'docs', value: 'inaccessible' })
 
 t.create('doc percent (unexpected response)')
   .get('/metrics/doc-percent/AFNetworking.json')
-  .intercept(nock => nock('https://metrics.cocoapods.org')
-    .get('/api/v1/pods/AFNetworking')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://metrics.cocoapods.org')
+      .get('/api/v1/pods/AFNetworking')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'docs', value: 'invalid'});
-
+  .expectJSON({ name: 'docs', value: 'invalid' })
 
 // downloads endpoints
 
 t.create('downloads (valid, monthly)')
   .get('/dm/AFNetworking.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriodAllowZero
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriodAllowZero,
+    })
+  )
 
 t.create('downloads (valid, weekly)')
   .get('/dw/AFNetworking.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriodAllowZero
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriodAllowZero,
+    })
+  )
 
 t.create('downloads (valid, total)')
   .get('/dt/AFNetworking.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricAllowZero
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricAllowZero,
+    })
+  )
 
 t.create('downloads (not found)')
   .get('/dt/not-a-package.json')
-  .expectJSON({name: 'downloads', value: 'not found'});
+  .expectJSON({ name: 'downloads', value: 'not found' })
 
 t.create('downloads (connection error)')
   .get('/dt/AFNetworking.json')
   .networkOff()
-  .expectJSON({name: 'downloads', value: 'inaccessible'});
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 t.create('downloads (unexpected response)')
   .get('/dt/AFNetworking.json')
-  .intercept(nock => nock('https://metrics.cocoapods.org')
-    .get('/api/v1/pods/AFNetworking')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://metrics.cocoapods.org')
+      .get('/api/v1/pods/AFNetworking')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'downloads', value: 'invalid'});
-
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 // apps endpoints
 
 t.create('apps (valid, weekly)')
   .get('/aw/AFNetworking.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'apps',
-    value: isMetricOverTimePeriodAllowZero
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'apps',
+      value: isMetricOverTimePeriodAllowZero,
+    })
+  )
 
 t.create('apps (valid, total)')
   .get('/at/AFNetworking.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'apps',
-    value: isMetricAllowZero
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'apps',
+      value: isMetricAllowZero,
+    })
+  )
 
 t.create('apps (not found)')
   .get('/at/not-a-package.json')
-  .expectJSON({name: 'apps', value: 'not found'});
+  .expectJSON({ name: 'apps', value: 'not found' })
 
 t.create('apps (connection error)')
   .get('/at/AFNetworking.json')
   .networkOff()
-  .expectJSON({name: 'apps', value: 'inaccessible'});
+  .expectJSON({ name: 'apps', value: 'inaccessible' })
 
 t.create('apps (unexpected response)')
   .get('/at/AFNetworking.json')
-  .intercept(nock => nock('https://metrics.cocoapods.org')
-    .get('/api/v1/pods/AFNetworking')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://metrics.cocoapods.org')
+      .get('/api/v1/pods/AFNetworking')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'apps', value: 'invalid'});
+  .expectJSON({ name: 'apps', value: 'invalid' })
diff --git a/services/codeclimate/codeclimate.tester.js b/services/codeclimate/codeclimate.tester.js
index 012b883cd78d0184dcfa470c3b79f0a3a57d8b7a..02f907c47a8de12c2b91075c948bcef0ba7afd58 100644
--- a/services/codeclimate/codeclimate.tester.js
+++ b/services/codeclimate/codeclimate.tester.js
@@ -1,121 +1,140 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const {
-  isIntegerPercentage,
-} = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isIntegerPercentage } = require('../test-validators')
 
 const t = new ServiceTester({ id: 'codeclimate', title: 'Code Climate' })
 
 // Tests based on Code Climate's test reports endpoint.
 t.create('test coverage percentage')
   .get('/c/jekyll/jekyll.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'coverage',
-    value: isIntegerPercentage
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'coverage',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('test coverage percentage alternative coverage URL')
   .get('/coverage/jekyll/jekyll.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'coverage',
-    value: isIntegerPercentage
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'coverage',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('test coverage percentage alternative top-level URL')
   .get('/jekyll/jekyll.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'coverage',
-    value: isIntegerPercentage
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'coverage',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('test coverage letter')
   .get('/c-letter/jekyll/jekyll.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'coverage',
-    value: Joi.equal('A', 'B', 'C', 'D', 'E', 'F')
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'coverage',
+      value: Joi.equal('A', 'B', 'C', 'D', 'E', 'F'),
+    })
+  )
 
 t.create('test coverage percentage for non-existent repo')
   .get('/c/unknown/unknown.json')
   .expectJSON({
     name: 'coverage',
-    value: 'not found'
-  });
+    value: 'not found',
+  })
 
 t.create('test coverage percentage for repo without test reports')
   .get('/c/angular/angular.js.json')
   .expectJSON({
     name: 'coverage',
-    value: 'unknown'
-  });
+    value: 'unknown',
+  })
 
 // Tests based on Code Climate's snapshots endpoint.
 t.create('issues count')
   .get('/issues/angular/angular.js.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'issues',
-    value: Joi.number().integer().positive()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'issues',
+      value: Joi.number()
+        .integer()
+        .positive(),
+    })
+  )
 
 t.create('technical debt percentage')
   .get('/tech-debt/angular/angular.js.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'technical debt',
-    value: isIntegerPercentage
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'technical debt',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('maintainability percentage')
   .get('/maintainability-percentage/angular/angular.js.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'maintainability',
-    value: isIntegerPercentage
-  }));
-
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'maintainability',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('maintainability letter')
   .get('/maintainability/angular/angular.js.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'maintainability',
-    value: Joi.equal('A', 'B', 'C', 'D', 'E', 'F')
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'maintainability',
+      value: Joi.equal('A', 'B', 'C', 'D', 'E', 'F'),
+    })
+  )
 
 t.create('maintainability letter for non-existent repo')
   .get('/maintainability/unknown/unknown.json')
   .expectJSON({
     name: 'maintainability',
-    value: 'not found'
-  });
+    value: 'not found',
+  })
 
 t.create('maintainability letter for repo without snapshots')
   .get('/maintainability/kabisaict/flow.json')
   .expectJSON({
     name: 'maintainability',
-    value: 'unknown'
-  });
+    value: 'unknown',
+  })
 
 t.create('malformed response for outer user repos query')
   .get('/maintainability/angular/angular.js.json')
-  .intercept(nock => nock('https://api.codeclimate.com')
-    .get('/v1/repos?github_slug=angular/angular.js')
-    .reply(200, {
-      data: [{}] // No relationships in the list of data elements.
-    }))
+  .intercept(nock =>
+    nock('https://api.codeclimate.com')
+      .get('/v1/repos?github_slug=angular/angular.js')
+      .reply(200, {
+        data: [{}], // No relationships in the list of data elements.
+      })
+  )
   .expectJSON({
     name: 'maintainability',
-    value: 'invalid'
-  });
+    value: 'invalid',
+  })
 
 t.create('malformed response for inner specific repo query')
   .get('/maintainability/angular/angular.js.json')
-  .intercept(nock => nock('https://api.codeclimate.com', {allowUnmocked: true})
-    .get(/\/v1\/repos\/[a-z0-9]+\/snapshots\/[a-z0-9]+/)
-    .reply(200, {})) // No data.
+  .intercept(nock =>
+    nock('https://api.codeclimate.com', { allowUnmocked: true })
+      .get(/\/v1\/repos\/[a-z0-9]+\/snapshots\/[a-z0-9]+/)
+      .reply(200, {})
+  ) // No data.
   .networkOn() // Combined with allowUnmocked: true, this allows the outer user repos query to go through.
   .expectJSON({
     name: 'maintainability',
-    value: 'invalid'
-  });
+    value: 'invalid',
+  })
 
-module.exports = t;
+module.exports = t
diff --git a/services/codecov/codecov.tester.js b/services/codecov/codecov.tester.js
index 7d55f140d90a0aabdf7c5bcffafba15fafe0b929..5f5b72f713bc9537dc8a954412a90b90aa574685 100644
--- a/services/codecov/codecov.tester.js
+++ b/services/codecov/codecov.tester.js
@@ -1,22 +1,26 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isIntegerPercentage } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isIntegerPercentage } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'codecov', title: 'Codecov.io' });
-module.exports = t;
+const t = new ServiceTester({ id: 'codecov', title: 'Codecov.io' })
+module.exports = t
 
 t.create('gets coverage status')
   .get('/c/github/codecov/example-python.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'coverage',
-    value: isIntegerPercentage,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'coverage',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('gets coverate status for branch')
   .get('/c/github/codecov/example-python/master.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'coverage',
-    value: isIntegerPercentage,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'coverage',
+      value: isIntegerPercentage,
+    })
+  )
diff --git a/services/codeship/codeship.tester.js b/services/codeship/codeship.tester.js
index fae9d714323e3fa4ef1ce503ac8e389b70a1c939..70adb3ce5110e7b90ffee78b4ed0c62a8cf281f1 100644
--- a/services/codeship/codeship.tester.js
+++ b/services/codeship/codeship.tester.js
@@ -1,54 +1,59 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isBuildStatus } = require('../test-validators');
-
-const t = new ServiceTester({ id: 'codeship', title: 'codeship' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isBuildStatus } = require('../test-validators')
 
+const t = new ServiceTester({ id: 'codeship', title: 'codeship' })
+module.exports = t
 
 t.create('codeship (valid, no branch)')
   .get('/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: isBuildStatus,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: isBuildStatus,
+    })
+  )
 
 t.create('codeship (valid, with branch)')
   .get('/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1/master.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: isBuildStatus,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: isBuildStatus,
+    })
+  )
 
 t.create('codeship (repo not found)')
   .get('/not-a-repo.json')
-  .expectJSON({name: 'build', value: 'not found'});
+  .expectJSON({ name: 'build', value: 'not found' })
 
 t.create('codeship (branch not found)')
   .get('/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1/not-a-branch.json')
-  .expectJSON({name: 'build', value: 'branch not found'});
+  .expectJSON({ name: 'build', value: 'branch not found' })
 
 t.create('codeship (connection error)')
   .get('/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1.json')
   .networkOff()
-  .expectJSON({name: 'build', value: 'inaccessible'});
+  .expectJSON({ name: 'build', value: 'inaccessible' })
 
 t.create('codeship (unexpected response header)')
   .get('/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1.json')
-  .intercept(nock => nock('https://codeship.com')
-    .get('/projects/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1/status')
-    .reply(200, "", {
-       'content-disposition': 'foo'
-     })
+  .intercept(nock =>
+    nock('https://codeship.com')
+      .get('/projects/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1/status')
+      .reply(200, '', {
+        'content-disposition': 'foo',
+      })
   )
-  .expectJSON({name: 'build', value: 'unknown'});
+  .expectJSON({ name: 'build', value: 'unknown' })
 
 t.create('codeship (unexpected response body)')
   .get('/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1.json')
-  .intercept(nock => nock('https://codeship.com')
-    .get('/projects/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1/status')
-    .reply(200, "")
+  .intercept(nock =>
+    nock('https://codeship.com')
+      .get('/projects/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1/status')
+      .reply(200, '')
   )
-  .expectJSON({name: 'build', value: 'invalid'});
+  .expectJSON({ name: 'build', value: 'invalid' })
diff --git a/services/codetally/codetally.tester.js b/services/codetally/codetally.tester.js
index 6ed3167ddac7500633b4ab2ba36752cdf8bb4356..40d6d6839b64fab0aca75df932b441887c944e16 100644
--- a/services/codetally/codetally.tester.js
+++ b/services/codetally/codetally.tester.js
@@ -1,10 +1,10 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'codetally', title: 'Codetally' });
-module.exports = t;
+const t = new ServiceTester({ id: 'codetally', title: 'Codetally' })
+module.exports = t
 
 // This test will extract the currency value from the
 // string value response from the server.
@@ -15,16 +15,23 @@ module.exports = t;
 
 t.create('Codetally')
   .get('/triggerman722/colorstrap.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'codetally',
-    value: Joi.string().regex(/\b\d+(?:.\d+)?/)
-  }));
-
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'codetally',
+      value: Joi.string().regex(/\b\d+(?:.\d+)?/),
+    })
+  )
 
 t.create('Empty')
   .get('/triggerman722/colorstrap.json')
-  .intercept(nock => nock('http://www.codetally.com')
-    .get('/formattedshield/triggerman722/colorstrap')
-    .reply(200, { currency_sign: '$', amount: '0.00', multiplier: '', currency_abbreviation: 'CAD' })
+  .intercept(nock =>
+    nock('http://www.codetally.com')
+      .get('/formattedshield/triggerman722/colorstrap')
+      .reply(200, {
+        currency_sign: '$',
+        amount: '0.00',
+        multiplier: '',
+        currency_abbreviation: 'CAD',
+      })
   )
-  .expectJSON({ name: 'codetally', value: ' $0.00 '});
+  .expectJSON({ name: 'codetally', value: ' $0.00 ' })
diff --git a/services/conda/conda.tester.js b/services/conda/conda.tester.js
index 41c8f1312a8d642a46b9cf1e72809bd03a055028..7bdf975fb1d261a84c0221ddd0d9c93fe292d3e1 100644
--- a/services/conda/conda.tester.js
+++ b/services/conda/conda.tester.js
@@ -1,101 +1,113 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const {
-  isVPlusTripleDottedVersion,
-  isMetric
-} = require('../test-validators');
-const { invalidJSON } = require('../response-fixtures');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isVPlusTripleDottedVersion, isMetric } = require('../test-validators')
+const { invalidJSON } = require('../response-fixtures')
 
-const isCondaPlatform = Joi.string().regex(/^\w+-\d+( \| \w+-\d+)*$/);
+const isCondaPlatform = Joi.string().regex(/^\w+-\d+( \| \w+-\d+)*$/)
 
-const t = new ServiceTester({id: 'conda', title: 'Conda'});
-module.exports = t;
+const t = new ServiceTester({ id: 'conda', title: 'Conda' })
+module.exports = t
 
 t.create('version')
   .get('/v/conda-forge/zlib.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'conda|conda-forge',
-    value: isVPlusTripleDottedVersion
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'conda|conda-forge',
+      value: isVPlusTripleDottedVersion,
+    })
+  )
 
 t.create('version (relabel)')
   .get('/v/conda-forge/zlib.json?label=123')
-  .expectJSONTypes(Joi.object().keys({
-    name: '123',
-    value: isVPlusTripleDottedVersion
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: '123',
+      value: isVPlusTripleDottedVersion,
+    })
+  )
 
 t.create('version (skip prefix)')
   .get('/vn/conda-forge/zlib.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'conda-forge',
-    value: isVPlusTripleDottedVersion
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'conda-forge',
+      value: isVPlusTripleDottedVersion,
+    })
+  )
 
 t.create('version (skip prefix, relabel)')
   .get('/vn/conda-forge/zlib.json?label=123')
-  .expectJSONTypes(Joi.object().keys({
-    name: '123',
-    value: isVPlusTripleDottedVersion
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: '123',
+      value: isVPlusTripleDottedVersion,
+    })
+  )
 
 t.create('platform')
   .get('/p/conda-forge/zlib.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'conda|platform',
-    value: isCondaPlatform
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'conda|platform',
+      value: isCondaPlatform,
+    })
+  )
 
 t.create('platform (skip prefix)')
   .get('/pn/conda-forge/zlib.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'platform',
-    value: isCondaPlatform
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'platform',
+      value: isCondaPlatform,
+    })
+  )
 
 t.create('platform (skip prefix,relabel)')
   .get('/pn/conda-forge/zlib.json?label=123')
-  .expectJSONTypes(Joi.object().keys({ name: '123', value: isCondaPlatform }));
+  .expectJSONTypes(Joi.object().keys({ name: '123', value: isCondaPlatform }))
 
 t.create('downloads')
   .get('/d/conda-forge/zlib.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'conda|downloads',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'conda|downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('downloads (skip prefix)')
   .get('/dn/conda-forge/zlib.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }))
 
 t.create('downloads (skip prefix, relabel)')
   .get('/dn/conda-forge/zlib.json?label=123')
-  .expectJSONTypes(Joi.object().keys({ name: '123', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: '123', value: isMetric }))
 
 t.create('unknown package')
   .get('/d/conda-forge/some-bogus-package-that-never-exists.json')
-  .expectJSON({ name: 'conda|downloads', value: 'invalid' });
+  .expectJSON({ name: 'conda|downloads', value: 'invalid' })
 
 t.create('unknown channel')
   .get('/d/some-bogus-channel-that-never-exists/zlib.json')
-  .expectJSON({ name: 'conda|downloads', value: 'invalid' });
+  .expectJSON({ name: 'conda|downloads', value: 'invalid' })
 
 t.create('unknown info')
   .get('/x/conda-forge/zlib.json')
   .expectStatus(404)
-  .expectJSON({ name: '404', value: 'badge not found' });
+  .expectJSON({ name: '404', value: 'badge not found' })
 
 t.create('connection error')
   .get('/d/conda-forge/zlib.json')
   .networkOff()
-  .expectJSON({ name: 'conda|downloads', value: 'inaccessible' });
+  .expectJSON({ name: 'conda|downloads', value: 'inaccessible' })
 
 t.create('unexpected response')
   .get('/v/conda-forge/zlib.json')
-  .intercept(nock => nock('https://api.anaconda.org')
-    .get('/package/conda-forge/zlib')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.anaconda.org')
+      .get('/package/conda-forge/zlib')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'conda|conda-forge', value: 'invalid'});
+  .expectJSON({ name: 'conda|conda-forge', value: 'invalid' })
diff --git a/services/continuousphp/continuousphp.tester.js b/services/continuousphp/continuousphp.tester.js
index d3cd85b9746c3cbab16951e7ea9ecda134831c8c..7108eb6c4b347dd67056774c5fc0e2fd20f98797 100644
--- a/services/continuousphp/continuousphp.tester.js
+++ b/services/continuousphp/continuousphp.tester.js
@@ -1,31 +1,35 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isBuildStatus } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isBuildStatus } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'continuousphp', title: 'continuousphp' });
-module.exports = t;
+const t = new ServiceTester({ id: 'continuousphp', title: 'continuousphp' })
+module.exports = t
 
 t.create('build status on default branch')
   .get('/git-hub/doctrine/dbal.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('build status on named branch')
   .get('/git-hub/doctrine/dbal/develop.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('unknown repo')
   .get('/git-hub/this-repo/does-not-exist.json')
-  .expectJSON({ name: 'build', value: 'invalid' });
+  .expectJSON({ name: 'build', value: 'invalid' })
 
 t.create('connection error')
   .get('/git-hub/doctrine/dbal.json')
   .networkOff()
-  .expectJSON({ name: 'build', value: 'invalid' });
+  .expectJSON({ name: 'build', value: 'invalid' })
diff --git a/services/coveralls/coveralls.tester.js b/services/coveralls/coveralls.tester.js
index bc095d3b91fed4e82e74f651af1bd8c53ef4190f..87a08f3219686c06c3b7d12b8bd12b3bed856d96 100644
--- a/services/coveralls/coveralls.tester.js
+++ b/services/coveralls/coveralls.tester.js
@@ -1,103 +1,152 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isIntegerPercentage } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isIntegerPercentage } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'coveralls', title: 'Coveralls.io' });
-module.exports = t;
+const t = new ServiceTester({ id: 'coveralls', title: 'Coveralls.io' })
+module.exports = t
 
 t.create('error status code - location header is missing')
   .get('/github/not/existed.json')
-  .intercept(nock => nock('https://coveralls.io')
-    .head('/repos/github/not/existed/badge.svg')
-    .reply(404)
+  .intercept(nock =>
+    nock('https://coveralls.io')
+      .head('/repos/github/not/existed/badge.svg')
+      .reply(404)
   )
-  .expectJSON({ name: 'coverage', value: 'invalid' });
+  .expectJSON({ name: 'coverage', value: 'invalid' })
 
 t.create('malformed location')
   .get('/github/user/repository.json')
-  .intercept(nock => nock('https://coveralls.io')
-    .head('/repos/github/user/repository/badge.svg')
-    .reply(302, {}, {
-      'Location': 'https://s3.amazonaws.com/assets.coveralls.io/badges/malformedlocation.svg'
-    })
+  .intercept(nock =>
+    nock('https://coveralls.io')
+      .head('/repos/github/user/repository/badge.svg')
+      .reply(
+        302,
+        {},
+        {
+          Location:
+            'https://s3.amazonaws.com/assets.coveralls.io/badges/malformedlocation.svg',
+        }
+      )
   )
-  .expectJSON({ name: 'coverage', value: 'malformed' });
+  .expectJSON({ name: 'coverage', value: 'malformed' })
 
 t.create('NaN percentage in location')
   .get('/github/user/repository.json')
-  .intercept(nock => nock('https://coveralls.io')
-    .head('/repos/github/user/repository/badge.svg')
-    .reply(302, {}, {
-      'Location': 'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_notanumber.svg'
-    })
+  .intercept(nock =>
+    nock('https://coveralls.io')
+      .head('/repos/github/user/repository/badge.svg')
+      .reply(
+        302,
+        {},
+        {
+          Location:
+            'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_notanumber.svg',
+        }
+      )
   )
-  .expectJSON({ name: 'coverage', value: 'unknown' });
+  .expectJSON({ name: 'coverage', value: 'unknown' })
 
 t.create('connection error')
   .get('/github/user/repository.json')
   .networkOff()
-  .expectJSON({ name: 'coverage', value: 'invalid' });
+  .expectJSON({ name: 'coverage', value: 'invalid' })
 
 t.create('show coverage')
   .get('/github/user/repository.json')
-  .intercept(nock => nock('https://coveralls.io')
-    .head('/repos/github/user/repository/badge.svg')
-    .reply(302, {}, {
-      'Location': 'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg'
-    })
+  .intercept(nock =>
+    nock('https://coveralls.io')
+      .head('/repos/github/user/repository/badge.svg')
+      .reply(
+        302,
+        {},
+        {
+          Location:
+            'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg',
+        }
+      )
   )
-  .expectJSON({ name: 'coverage', value: '50%' });
+  .expectJSON({ name: 'coverage', value: '50%' })
 
 t.create('show coverage for legacy github link')
   .get('/user/repository.json')
-  .intercept(nock => nock('https://coveralls.io')
-    .head('/repos/github/user/repository/badge.svg')
-    .reply(302, {}, {
-      'Location': 'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg'
-    })
+  .intercept(nock =>
+    nock('https://coveralls.io')
+      .head('/repos/github/user/repository/badge.svg')
+      .reply(
+        302,
+        {},
+        {
+          Location:
+            'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg',
+        }
+      )
   )
-  .expectJSON({ name: 'coverage', value: '50%' });
+  .expectJSON({ name: 'coverage', value: '50%' })
 
 t.create('show coverage for branch')
   .get('/github/user/repository/branch.json')
-  .intercept(nock => nock('https://coveralls.io')
-    .head('/repos/github/user/repository/badge.svg?branch=branch')
-    .reply(302, {}, {
-      'Location': 'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg'
-    })
+  .intercept(nock =>
+    nock('https://coveralls.io')
+      .head('/repos/github/user/repository/badge.svg?branch=branch')
+      .reply(
+        302,
+        {},
+        {
+          Location:
+            'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg',
+        }
+      )
   )
-  .expectJSON({ name: 'coverage', value: '50%' });
+  .expectJSON({ name: 'coverage', value: '50%' })
 
 t.create('show coverage for bitbucket')
   .get('/bitbucket/user/repository.json')
-  .intercept(nock => nock('https://coveralls.io')
-    .head('/repos/bitbucket/user/repository/badge.svg')
-    .reply(302, {}, {
-      'Location': 'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg'
-    })
+  .intercept(nock =>
+    nock('https://coveralls.io')
+      .head('/repos/bitbucket/user/repository/badge.svg')
+      .reply(
+        302,
+        {},
+        {
+          Location:
+            'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg',
+        }
+      )
   )
-  .expectJSON({ name: 'coverage', value: '50%' });
+  .expectJSON({ name: 'coverage', value: '50%' })
 
 t.create('show coverage for bitbucket with branch')
   .get('/bitbucket/user/repository/branch.json')
-  .intercept(nock => nock('https://coveralls.io')
-    .head('/repos/bitbucket/user/repository/badge.svg?branch=branch')
-    .reply(302, {}, {
-      'Location': 'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg'
-    })
+  .intercept(nock =>
+    nock('https://coveralls.io')
+      .head('/repos/bitbucket/user/repository/badge.svg?branch=branch')
+      .reply(
+        302,
+        {},
+        {
+          Location:
+            'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg',
+        }
+      )
   )
-  .expectJSON({ name: 'coverage', value: '50%' });
+  .expectJSON({ name: 'coverage', value: '50%' })
 
 t.create('github coverage')
   .get('/github/jekyll/jekyll.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'coverage', value: isIntegerPercentage }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'coverage', value: isIntegerPercentage })
+  )
 
 t.create('github coverage for legacy link')
   .get('/jekyll/jekyll.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'coverage', value: isIntegerPercentage }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'coverage', value: isIntegerPercentage })
+  )
 
 t.create('bitbucket coverage')
   .get('/bitbucket/pyKLIP/pyklip.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'coverage', value: isIntegerPercentage }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'coverage', value: isIntegerPercentage })
+  )
diff --git a/services/cran/cran.tester.js b/services/cran/cran.tester.js
index f5ed483552c2e56537bad07bd0f3adb38ec8202d..36f5b4ca40f67c0c44893513dd3b60d28e32eee8 100644
--- a/services/cran/cran.tester.js
+++ b/services/cran/cran.tester.js
@@ -1,47 +1,53 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isVPlusTripleDottedVersion } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isVPlusTripleDottedVersion } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'cran', title: 'CRAN/METACRAN' });
-module.exports = t;
+const t = new ServiceTester({ id: 'cran', title: 'CRAN/METACRAN' })
+module.exports = t
 
 t.create('version')
   .get('/v/devtools.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'cran',
-    value: isVPlusTripleDottedVersion
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'cran',
+      value: isVPlusTripleDottedVersion,
+    })
+  )
 
 t.create('specified license')
   .get('/l/devtools.json')
-  .expectJSON({ name: 'license', value: 'GPL (>= 2)' });
+  .expectJSON({ name: 'license', value: 'GPL (>= 2)' })
 
 t.create('unknown package')
   .get('/l/some-bogus-package.json')
-  .expectJSON({ name: 'cran', value: 'not found' });
+  .expectJSON({ name: 'cran', value: 'not found' })
 
 t.create('unknown info')
   .get('/z/devtools.json')
   .expectStatus(404)
-  .expectJSON({ name: '404', value: 'badge not found' });
+  .expectJSON({ name: '404', value: 'badge not found' })
 
 t.create('malformed response')
   .get('/v/foobar.json')
-  .intercept(nock => nock('http://crandb.r-pkg.org')
-    .get('/foobar')
-    .reply(200))  // JSON without Version.
-  .expectJSON({ name: 'cran', value: 'invalid' });
+  .intercept(nock =>
+    nock('http://crandb.r-pkg.org')
+      .get('/foobar')
+      .reply(200)
+  ) // JSON without Version.
+  .expectJSON({ name: 'cran', value: 'invalid' })
 
 t.create('connection error')
   .get('/v/foobar.json')
   .networkOff()
-  .expectJSON({ name: 'cran', value: 'inaccessible' });
+  .expectJSON({ name: 'cran', value: 'inaccessible' })
 
 t.create('unspecified license')
   .get('/l/foobar.json')
-  .intercept(nock => nock('http://crandb.r-pkg.org')
-    .get('/foobar')
-    .reply(200, {}))  // JSON without License.
-  .expectJSON({ name: 'license', value: 'unknown' });
+  .intercept(nock =>
+    nock('http://crandb.r-pkg.org')
+      .get('/foobar')
+      .reply(200, {})
+  ) // JSON without License.
+  .expectJSON({ name: 'license', value: 'unknown' })
diff --git a/services/crates/crates.tester.js b/services/crates/crates.tester.js
index c9431d4fc8cce87a4fbe8e508b8afaa5e4e5b157..dc33a5ec744ff437b0a24047d4b65a8b8186f343 100644
--- a/services/crates/crates.tester.js
+++ b/services/crates/crates.tester.js
@@ -1,14 +1,14 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'crates', title: 'crates.io' });
-module.exports = t;
+const t = new ServiceTester({ id: 'crates', title: 'crates.io' })
+module.exports = t
 
 t.create('license')
   .get('/l/libc.json')
-  .expectJSON({ name: 'license', value: 'MIT/Apache-2.0' });
+  .expectJSON({ name: 'license', value: 'MIT/Apache-2.0' })
 
 t.create('license (with version)')
   .get('/l/libc/0.2.31.json')
-  .expectJSON({ name: 'license', value: 'MIT/Apache-2.0' });
+  .expectJSON({ name: 'license', value: 'MIT/Apache-2.0' })
diff --git a/services/david/david.tester.js b/services/david/david.tester.js
index 4f7042c804207469b5def522de2377bf217395d0..7b2f39c9f0c1e19cc98714af26235d0949530353 100644
--- a/services/david/david.tester.js
+++ b/services/david/david.tester.js
@@ -1,70 +1,84 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
-const isDependencyStatus = Joi.string().valid('insecure', 'up to date', 'out of date');
-
-const t = new ServiceTester({ id: 'david', title: 'David' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
+const isDependencyStatus = Joi.string().valid(
+  'insecure',
+  'up to date',
+  'out of date'
+)
 
+const t = new ServiceTester({ id: 'david', title: 'David' })
+module.exports = t
 
 t.create('david dependencies (valid)')
   .get('/expressjs/express.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'dependencies',
-    value: isDependencyStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'dependencies',
+      value: isDependencyStatus,
+    })
+  )
 
 t.create('david dev dependencies (valid)')
   .get('/dev/expressjs/express.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'devDependencies',
-    value: isDependencyStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'devDependencies',
+      value: isDependencyStatus,
+    })
+  )
 
 t.create('david optional dependencies (valid)')
   .get('/optional/elnounch/byebye.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'optionalDependencies',
-    value: isDependencyStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'optionalDependencies',
+      value: isDependencyStatus,
+    })
+  )
 
 t.create('david peer dependencies (valid)')
   .get('/peer/webcomponents/generator-element.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'peerDependencies',
-    value: isDependencyStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'peerDependencies',
+      value: isDependencyStatus,
+    })
+  )
 
 t.create('david dependencies with path (valid)')
   .get('/babel/babel.json?path=packages/babel-core')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'dependencies',
-    value: isDependencyStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'dependencies',
+      value: isDependencyStatus,
+    })
+  )
 
 t.create('david dependencies (none)')
   .get('/peer/expressjs/express.json') // express does not specify peer dependencies
-  .expectJSON({name: 'peerDependencies', value: 'none'});
+  .expectJSON({ name: 'peerDependencies', value: 'none' })
 
 t.create('david dependencies (repo not found)')
   .get('/pyvesb/emptyrepo.json')
-  .expectJSON({name: 'dependencies', value: 'invalid'});
+  .expectJSON({ name: 'dependencies', value: 'invalid' })
 
 t.create('david dependencies (path not found')
   .get('/babel/babel.json?path=invalid/path')
-  .expectJSON({name: 'dependencies', value: 'invalid'});
+  .expectJSON({ name: 'dependencies', value: 'invalid' })
 
 t.create('david dependencies (connection error)')
   .get('/expressjs/express.json')
   .networkOff()
-  .expectJSON({name: 'dependencies', value: 'inaccessible'});
+  .expectJSON({ name: 'dependencies', value: 'inaccessible' })
 
 t.create('david dependencies (unexpected response)')
   .get('/expressjs/express.json')
-  .intercept(nock => nock('https://david-dm.org')
-    .get('/expressjs/express/info.json')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://david-dm.org')
+      .get('/expressjs/express/info.json')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'dependencies', value: 'invalid'});
+  .expectJSON({ name: 'dependencies', value: 'invalid' })
diff --git a/services/dependabot/dependabot.tester.js b/services/dependabot/dependabot.tester.js
index ebf8270f82ef9b7023464dee56e88d4dbfc4f3a5..f82f6c8a9faaceabebc7c5c67e616d637ce58e34 100644
--- a/services/dependabot/dependabot.tester.js
+++ b/services/dependabot/dependabot.tester.js
@@ -1,23 +1,26 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isIntegerPercentage } = require('../test-validators');
-const { invalidJSON } = require('../response-fixtures');
-const colorscheme = require('../../lib/colorscheme.json');
-const mapValues = require('lodash.mapvalues');
-const colorsB = mapValues(colorscheme, 'colorB');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isIntegerPercentage } = require('../test-validators')
+const { invalidJSON } = require('../response-fixtures')
+const colorscheme = require('../../lib/colorscheme.json')
+const mapValues = require('lodash.mapvalues')
+const colorsB = mapValues(colorscheme, 'colorB')
 
-const t = new ServiceTester({ id: 'dependabot', title: 'Dependabot' });
-module.exports = t;
+const t = new ServiceTester({ id: 'dependabot', title: 'Dependabot' })
+module.exports = t
 
 t.create('semver stability (valid)')
   .get('/semver/bundler/puma.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'semver stability',
-    value: isIntegerPercentage,
-    link: 'https://dependabot.com/compatibility-score.html?dependency-name=puma&package-manager=bundler&version-scheme=semver',
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'semver stability',
+      value: isIntegerPercentage,
+      link:
+        'https://dependabot.com/compatibility-score.html?dependency-name=puma&package-manager=bundler&version-scheme=semver',
+    })
+  )
 
 t.create('semver stability (connection error)')
   .get('/semver/bundler/puma.json?style=_shields_test')
@@ -25,31 +28,34 @@ t.create('semver stability (connection error)')
   .expectJSON({
     name: 'semver stability',
     value: 'inaccessible',
-    colorB: colorsB.red
-  });
+    colorB: colorsB.red,
+  })
 
 t.create('semver stability (invalid error)')
   .get('/semver/invalid-manager/puma.json?style=_shields_test')
   .expectJSON({
     name: 'semver stability',
     value: 'invalid',
-    colorB: colorsB.lightgrey
-  });
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('semver stability (invalid JSON response)')
   .get('/semver/bundler/puma.json')
-  .intercept(nock => nock('https://api.dependabot.com')
-     .get('/badges/compatibility_score?package-manager=bundler&dependency-name=puma&version-scheme=semver')
-     .reply(invalidJSON)
-   )
+  .intercept(nock =>
+    nock('https://api.dependabot.com')
+      .get(
+        '/badges/compatibility_score?package-manager=bundler&dependency-name=puma&version-scheme=semver'
+      )
+      .reply(invalidJSON)
+  )
   .expectJSON({
     name: 'semver stability',
-    value: 'invalid'
-  });
+    value: 'invalid',
+  })
 
 t.create('semver stability (missing dependency)')
   .get('/semver/bundler/some-random-missing-dependency.json')
   .expectJSON({
     name: 'semver stability',
     value: 'unknown',
-  });
+  })
diff --git a/services/depfu/depfu.tester.js b/services/depfu/depfu.tester.js
index 291fc51da3a039404d2e151ada30a303d602e55b..6e6786999aa7e6f08320cf5fd98fa22ac8b03e89 100644
--- a/services/depfu/depfu.tester.js
+++ b/services/depfu/depfu.tester.js
@@ -1,26 +1,32 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const isDependencyStatus = Joi.string().valid('insecure', 'latest', 'recent', 'stale');
-
-const t = new ServiceTester({ id: 'depfu', title: 'Depfu' });
-module.exports = t;
+const isDependencyStatus = Joi.string().valid(
+  'insecure',
+  'latest',
+  'recent',
+  'stale'
+)
 
+const t = new ServiceTester({ id: 'depfu', title: 'Depfu' })
+module.exports = t
 
 t.create('depfu dependencies (valid)')
   .get('/depfu/example-ruby.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'dependencies',
-    value: isDependencyStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'dependencies',
+      value: isDependencyStatus,
+    })
+  )
 
 t.create('depfu dependencies (repo not found)')
   .get('/pyvesb/emptyrepo.json')
-  .expectJSON({name: 'dependencies', value: 'invalid'});
+  .expectJSON({ name: 'dependencies', value: 'invalid' })
 
 t.create('depfu dependencies (connection error)')
   .get('/depfu/example-ruby.json')
   .networkOff()
-  .expectJSON({name: 'dependencies', value: 'inaccessible'});
+  .expectJSON({ name: 'dependencies', value: 'inaccessible' })
diff --git a/services/discord/discord.tester.js b/services/discord/discord.tester.js
index 5a47dbf27ceb07f76567a19ed4723a6af138db6b..f3aa86782af20559ed9b8ca3279c7069e578c200 100644
--- a/services/discord/discord.tester.js
+++ b/services/discord/discord.tester.js
@@ -1,42 +1,46 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'discord', title: 'Discord' });
-module.exports = t;
+const t = new ServiceTester({ id: 'discord', title: 'Discord' })
+module.exports = t
 
 t.create('gets status for Reactiflux')
   .get('/102860784329052160.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'chat',
-    value: Joi.string().regex(/^[0-9]+ online$/),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'chat',
+      value: Joi.string().regex(/^[0-9]+ online$/),
+    })
+  )
 
 t.create('invalid server ID')
   .get('/12345.json')
-  .expectJSON({ name: 'chat', value: 'invalid server' });
+  .expectJSON({ name: 'chat', value: 'invalid server' })
 
 t.create('widget disabled')
   .get('/12345.json')
-  .intercept(nock => nock('https://discordapp.com/')
-    .get('/api/guilds/12345/widget.json')
-    .reply(403, {
-      code: 50004,
-      message: 'Widget Disabled'
-    })
+  .intercept(nock =>
+    nock('https://discordapp.com/')
+      .get('/api/guilds/12345/widget.json')
+      .reply(403, {
+        code: 50004,
+        message: 'Widget Disabled',
+      })
   )
-  .expectJSON({ name: 'chat', value: 'widget disabled' });
+  .expectJSON({ name: 'chat', value: 'widget disabled' })
 
 t.create('server error')
   .get('/12345.json')
-  .intercept(nock => nock('https://discordapp.com/')
-    .get('/api/guilds/12345/widget.json')
-    .reply(500, 'Something broke')
+  .intercept(nock =>
+    nock('https://discordapp.com/')
+      .get('/api/guilds/12345/widget.json')
+      .reply(500, 'Something broke')
   )
-  .expectJSON({ name: 'chat', value: 'inaccessible' });
+  .expectJSON({ name: 'chat', value: 'inaccessible' })
 
 t.create('connection error')
   .get('/102860784329052160.json')
   .networkOff()
-  .expectJSON({ name: 'chat', value: 'inaccessible' });
+  .expectJSON({ name: 'chat', value: 'inaccessible' })
diff --git a/services/discourse/discourse.tester.js b/services/discourse/discourse.tester.js
index 33c5cca0de6b225e3818bd3f6302c87128460922..74bca839c0e6239e203bf95ea274631a0124d3b2 100644
--- a/services/discourse/discourse.tester.js
+++ b/services/discourse/discourse.tester.js
@@ -1,10 +1,10 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'discourse', title: 'Discourse' });
-module.exports = t;
+const t = new ServiceTester({ id: 'discourse', title: 'Discourse' })
+module.exports = t
 
 const data = {
   topic_count: 22513,
@@ -20,106 +20,122 @@ const data = {
   active_users_30_days: 1495,
   like_count: 308833,
   likes_7_days: 3633,
-  likes_30_days: 13397
-};
+  likes_30_days: 13397,
+}
 
 t.create('Topics')
   .get('/https/meta.discourse.org/topics.json')
-  .intercept(nock => nock('https://meta.discourse.org')
-    .get('/site/statistics.json')
-    .reply(200, data)
+  .intercept(nock =>
+    nock('https://meta.discourse.org')
+      .get('/site/statistics.json')
+      .reply(200, data)
   )
-  .expectJSON({ name: 'discourse', value: '23k topics' });
+  .expectJSON({ name: 'discourse', value: '23k topics' })
 
 t.create('Posts')
   .get('/https/meta.discourse.org/posts.json')
-  .intercept(nock => nock('https://meta.discourse.org')
-    .get('/site/statistics.json')
-    .reply(200, data)
+  .intercept(nock =>
+    nock('https://meta.discourse.org')
+      .get('/site/statistics.json')
+      .reply(200, data)
   )
-  .expectJSON({ name: 'discourse', value: '338k posts' });
+  .expectJSON({ name: 'discourse', value: '338k posts' })
 
 t.create('Users')
   .get('/https/meta.discourse.org/users.json')
-  .intercept(nock => nock('https://meta.discourse.org')
-    .get('/site/statistics.json')
-    .reply(200, data)
+  .intercept(nock =>
+    nock('https://meta.discourse.org')
+      .get('/site/statistics.json')
+      .reply(200, data)
   )
-  .expectJSON({ name: 'discourse', value: '31k users' });
+  .expectJSON({ name: 'discourse', value: '31k users' })
 
 t.create('Likes')
   .get('/https/meta.discourse.org/likes.json')
-  .intercept(nock => nock('https://meta.discourse.org')
-    .get('/site/statistics.json')
-    .reply(200, data)
+  .intercept(nock =>
+    nock('https://meta.discourse.org')
+      .get('/site/statistics.json')
+      .reply(200, data)
   )
-  .expectJSON({ name: 'discourse', value: '309k likes' });
+  .expectJSON({ name: 'discourse', value: '309k likes' })
 
 t.create('Status')
   .get('/https/meta.discourse.org/status.json')
-  .intercept(nock => nock('https://meta.discourse.org')
-    .get('/site/statistics.json')
-    .reply(200, data)
+  .intercept(nock =>
+    nock('https://meta.discourse.org')
+      .get('/site/statistics.json')
+      .reply(200, data)
   )
-  .expectJSON({ name: 'discourse', value: 'online' });
+  .expectJSON({ name: 'discourse', value: 'online' })
 
-  t.create('Status with http (not https)')
+t.create('Status with http (not https)')
   .get('/http/meta.discourse.org/status.json')
-  .intercept(nock => nock('http://meta.discourse.org')
-    .get('/site/statistics.json')
-    .reply(200, data)
+  .intercept(nock =>
+    nock('http://meta.discourse.org')
+      .get('/site/statistics.json')
+      .reply(200, data)
   )
-  .expectJSON({ name: 'discourse', value: 'online' });
+  .expectJSON({ name: 'discourse', value: 'online' })
 
 t.create('Invalid Host')
   .get('/https/some.host/status.json')
-  .intercept(nock => nock('https://some.host')
-    .get('/site/statistics.json')
-    .reply(404, "<h1>Not Found</h1>")
+  .intercept(nock =>
+    nock('https://some.host')
+      .get('/site/statistics.json')
+      .reply(404, '<h1>Not Found</h1>')
   )
-  .expectJSON({ name: 'discourse', value: 'inaccessible' });
+  .expectJSON({ name: 'discourse', value: 'inaccessible' })
 
 t.create('Invalid Stat')
   .get('/https/meta.discourse.org/unknown.json')
-  .intercept(nock => nock('https://meta.discourse.org')
-    .get('/site/statistics.json')
-    .reply(200, data)
+  .intercept(nock =>
+    nock('https://meta.discourse.org')
+      .get('/site/statistics.json')
+      .reply(200, data)
   )
-  .expectJSON({ name: 'discourse', value: 'invalid' });
+  .expectJSON({ name: 'discourse', value: 'invalid' })
 
 t.create('Connection Error')
   .get('/https/meta.discourse.org/status.json')
   .networkOff()
-  .expectJSON({ name: 'discourse', value: 'inaccessible' });
+  .expectJSON({ name: 'discourse', value: 'inaccessible' })
 
 t.create('Topics (live)')
   .get('/https/meta.discourse.org/topics.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'discourse',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? topics$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'discourse',
+      value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? topics$/),
+    })
+  )
 
 t.create('Posts (live)')
   .get('/https/meta.discourse.org/posts.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'discourse',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? posts$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'discourse',
+      value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? posts$/),
+    })
+  )
 
 t.create('Users (live)')
   .get('/https/meta.discourse.org/users.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'discourse',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? users$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'discourse',
+      value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? users$/),
+    })
+  )
 
 t.create('Likes (live)')
   .get('/https/meta.discourse.org/likes.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'discourse',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? likes$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'discourse',
+      value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? likes$/),
+    })
+  )
 
 t.create('Status (live)')
   .get('/https/meta.discourse.org/status.json')
-  .expectJSON({ name: 'discourse', value: 'online' });
\ No newline at end of file
+  .expectJSON({ name: 'discourse', value: 'online' })
diff --git a/services/dockbit/dockbit.tester.js b/services/dockbit/dockbit.tester.js
index 974f4c666efe1528048e96678b4618c10f56c398..8626b096fac0367fce3d363883b955fa91770230 100644
--- a/services/dockbit/dockbit.tester.js
+++ b/services/dockbit/dockbit.tester.js
@@ -1,44 +1,50 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'dockbit', title: 'Dockbit' });
-module.exports = t;
+const t = new ServiceTester({ id: 'dockbit', title: 'Dockbit' })
+module.exports = t
 
 t.create('deploy status')
   .get('/DockbitStatus/health.json?token=TvavttxFHJ4qhnKstDxrvBXM')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'deploy',
-    value: Joi.equal(
-      'success',
-      'failure',
-      'error',
-      'working',
-      'pending',
-      'rejected'
-    )
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'deploy',
+      value: Joi.equal(
+        'success',
+        'failure',
+        'error',
+        'working',
+        'pending',
+        'rejected'
+      ),
+    })
+  )
 
 t.create('unknown pipeline')
   .get('/DockbitStatus/unknown.json')
-  .expectJSON({ name: 'deploy', value: 'not found' });
+  .expectJSON({ name: 'deploy', value: 'not found' })
 
 t.create('no deploy status')
   .get('/foo/bar.json?token=123')
-  .intercept(nock => nock('https://dockbit.com/')
-    .get('/foo/bar/status/123')
-    .reply(200, {state: null}))
-  .expectJSON({ name: 'deploy', value: 'not found' });
+  .intercept(nock =>
+    nock('https://dockbit.com/')
+      .get('/foo/bar/status/123')
+      .reply(200, { state: null })
+  )
+  .expectJSON({ name: 'deploy', value: 'not found' })
 
 t.create('server error')
   .get('/foo/bar.json?token=123')
-  .intercept(nock => nock('https://dockbit.com/')
-    .get('/foo/bar/status/123')
-    .reply(500, 'Something went wrong'))
-  .expectJSON({ name: 'deploy', value: 'inaccessible' });
+  .intercept(nock =>
+    nock('https://dockbit.com/')
+      .get('/foo/bar/status/123')
+      .reply(500, 'Something went wrong')
+  )
+  .expectJSON({ name: 'deploy', value: 'inaccessible' })
 
 t.create('connection error')
   .get('/foo/bar.json')
   .networkOff()
-  .expectJSON({ name: 'deploy', value: 'inaccessible' });
+  .expectJSON({ name: 'deploy', value: 'inaccessible' })
diff --git a/services/docker/docker.tester.js b/services/docker/docker.tester.js
index 2f8c75e55715b8709f5e68edc3e116f27954f9f1..600f2ac25dbb645d218f08d7ff51706abe59f7e8 100644
--- a/services/docker/docker.tester.js
+++ b/services/docker/docker.tester.js
@@ -1,249 +1,298 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const colorscheme = require('../../lib/colorscheme.json');
-const mapValues = require('lodash.mapvalues');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const colorscheme = require('../../lib/colorscheme.json')
+const mapValues = require('lodash.mapvalues')
 
-const { isMetric } = require('../test-validators');
-const { invalidJSON } = require('../response-fixtures');
-const { isBuildStatus } = require('../test-validators');
-const isAutomatedBuildStatus = Joi.string().valid('automated', 'manual');
-const colorsB = mapValues(colorscheme, 'colorB');
-
-const t = new ServiceTester({ id: 'docker', title: 'Docker Hub' });
-module.exports = t;
+const { isMetric } = require('../test-validators')
+const { invalidJSON } = require('../response-fixtures')
+const { isBuildStatus } = require('../test-validators')
+const isAutomatedBuildStatus = Joi.string().valid('automated', 'manual')
+const colorsB = mapValues(colorscheme, 'colorB')
 
+const t = new ServiceTester({ id: 'docker', title: 'Docker Hub' })
+module.exports = t
 
 // stars endpoint
 
 t.create('docker stars (valid, library)')
   .get('/stars/_/ubuntu.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker stars',
-    value: isMetric,
-    colorB: Joi.any().equal('#066da5').required()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker stars',
+      value: isMetric,
+      colorB: Joi.any()
+        .equal('#066da5')
+        .required(),
+    })
+  )
 
 t.create('docker stars (override colorB)')
   .get('/stars/_/ubuntu.json?colorB=fedcba&style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker stars',
-    value: isMetric,
-    colorB: Joi.any().equal('#fedcba').required()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker stars',
+      value: isMetric,
+      colorB: Joi.any()
+        .equal('#fedcba')
+        .required(),
+    })
+  )
 
 t.create('docker stars (valid, user)')
   .get('/stars/jrottenberg/ffmpeg.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker stars',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker stars',
+      value: isMetric,
+    })
+  )
 
 t.create('docker stars (not found)')
   .get('/stars/_/not-a-real-repo.json')
-  .expectJSON({name: 'docker stars', value: 'repo not found'});
+  .expectJSON({ name: 'docker stars', value: 'repo not found' })
 
 t.create('docker stars (connection error)')
   .get('/stars/_/ubuntu.json')
   .networkOff()
-  .expectJSON({name: 'docker stars', value: 'inaccessible'});
+  .expectJSON({ name: 'docker stars', value: 'inaccessible' })
 
 t.create('docker stars (unexpected response)')
   .get('/stars/_/ubuntu.json')
-  .intercept(nock => nock('https://hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu/stars/count/')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu/stars/count/')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'docker stars', value: 'invalid'});
-
+  .expectJSON({ name: 'docker stars', value: 'invalid' })
 
 // pulls endpoint
 
 t.create('docker pulls (valid, library)')
   .get('/pulls/_/ubuntu.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker pulls',
-    value: isMetric,
-    colorB: Joi.any().equal('#066da5').required()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker pulls',
+      value: isMetric,
+      colorB: Joi.any()
+        .equal('#066da5')
+        .required(),
+    })
+  )
 
 t.create('docker pulls (override colorB)')
   .get('/pulls/_/ubuntu.json?colorB=fedcba&style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker pulls',
-    value: isMetric,
-    colorB: Joi.any().equal('#fedcba').required()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker pulls',
+      value: isMetric,
+      colorB: Joi.any()
+        .equal('#fedcba')
+        .required(),
+    })
+  )
 
 t.create('docker pulls (valid, user)')
   .get('/pulls/jrottenberg/ffmpeg.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker pulls',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker pulls',
+      value: isMetric,
+    })
+  )
 
 t.create('docker pulls (not found)')
   .get('/pulls/_/not-a-real-repo.json')
-  .expectJSON({name: 'docker pulls', value: 'repo not found'});
+  .expectJSON({ name: 'docker pulls', value: 'repo not found' })
 
 t.create('docker pulls (connection error)')
   .get('/pulls/_/ubuntu.json')
   .networkOff()
-  .expectJSON({name: 'docker pulls', value: 'inaccessible'});
+  .expectJSON({ name: 'docker pulls', value: 'inaccessible' })
 
 t.create('docker pulls (unexpected response)')
   .get('/pulls/_/ubuntu.json')
-  .intercept(nock => nock('https://hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'docker pulls', value: 'invalid'});
-
+  .expectJSON({ name: 'docker pulls', value: 'invalid' })
 
 // automated build endpoint
 
 t.create('docker automated build (valid, library)')
   .get('/automated/_/ubuntu.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker build',
-    value: isAutomatedBuildStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker build',
+      value: isAutomatedBuildStatus,
+    })
+  )
 
 t.create('docker automated build (valid, user)')
   .get('/automated/jrottenberg/ffmpeg.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker build',
-    value: isAutomatedBuildStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker build',
+      value: isAutomatedBuildStatus,
+    })
+  )
 
 t.create('docker automated build (not found)')
   .get('/automated/_/not-a-real-repo.json')
-  .expectJSON({name: 'docker build', value: 'repo not found'});
+  .expectJSON({ name: 'docker build', value: 'repo not found' })
 
 t.create('docker automated build (connection error)')
   .get('/automated/_/ubuntu.json')
   .networkOff()
-  .expectJSON({name: 'docker build', value: 'inaccessible'});
+  .expectJSON({ name: 'docker build', value: 'inaccessible' })
 
 t.create('docker automated build (unexpected response)')
   .get('/automated/_/ubuntu.json')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'docker build', value: 'invalid'});
+  .expectJSON({ name: 'docker build', value: 'invalid' })
 
 t.create('docker automated build - automated')
   .get('/automated/_/ubuntu.json?style=_shields_test')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu')
-    .reply(200, {is_automated: true})
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu')
+      .reply(200, { is_automated: true })
   )
-  .expectJSON({name: 'docker build', value: 'automated', colorB: '#066da5'});
+  .expectJSON({ name: 'docker build', value: 'automated', colorB: '#066da5' })
 
 t.create('docker automated build - manual')
   .get('/automated/_/ubuntu.json?style=_shields_test')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu')
-    .reply(200, {is_automated: false})
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu')
+      .reply(200, { is_automated: false })
   )
-  .expectJSON({name: 'docker build', value: 'manual', colorB: colorsB.yellow});
+  .expectJSON({ name: 'docker build', value: 'manual', colorB: colorsB.yellow })
 
 t.create('docker automated build - colorB override in manual')
   .get('/automated/_/ubuntu.json?colorB=fedcba&style=_shields_test')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu')
-    .reply(200, {is_automated: false})
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu')
+      .reply(200, { is_automated: false })
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker build',
+      value: isAutomatedBuildStatus,
+      colorB: Joi.any()
+        .equal('#fedcba')
+        .required(),
+    })
   )
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker build',
-    value: isAutomatedBuildStatus,
-    colorB: Joi.any().equal('#fedcba').required()
-  }));
 
 t.create('docker automated build - colorB override in automated')
   .get('/automated/_/ubuntu.json?colorB=fedcba&style=_shields_test')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu')
-    .reply(200, {is_automated: true})
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu')
+      .reply(200, { is_automated: true })
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker build',
+      value: isAutomatedBuildStatus,
+      colorB: Joi.any()
+        .equal('#fedcba')
+        .required(),
+    })
   )
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker build',
-    value: isAutomatedBuildStatus,
-    colorB: Joi.any().equal('#fedcba').required()
-  }));
 
 // build status endpoint
 
 t.create('docker build status (valid, user)')
   .get('/build/jrottenberg/ffmpeg.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docker build',
-    value: isBuildStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docker build',
+      value: isBuildStatus,
+    })
+  )
 
 t.create('docker build status (not found)')
   .get('/build/_/not-a-real-repo.json')
-  .expectJSON({name: 'docker build', value: 'repo not found'});
+  .expectJSON({ name: 'docker build', value: 'repo not found' })
 
 t.create('docker build status (connection error)')
   .get('/build/_/ubuntu.json')
   .networkOff()
-  .expectJSON({name: 'docker build', value: 'inaccessible'});
+  .expectJSON({ name: 'docker build', value: 'inaccessible' })
 
 t.create('docker build status (unexpected response)')
   .get('/build/_/ubuntu.json')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu/buildhistory')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu/buildhistory')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'docker build', value: 'invalid'});
+  .expectJSON({ name: 'docker build', value: 'invalid' })
 
 t.create('docker build status (passing)')
   .get('/build/_/ubuntu.json?style=_shields_test')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu/buildhistory')
-    .reply(200, {results: [{status: 10}]})
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu/buildhistory')
+      .reply(200, { results: [{ status: 10 }] })
   )
-  .expectJSON({name: 'docker build', value: 'passing', colorB: colorsB.brightgreen});
+  .expectJSON({
+    name: 'docker build',
+    value: 'passing',
+    colorB: colorsB.brightgreen,
+  })
 
 t.create('docker build status (failing)')
   .get('/build/_/ubuntu.json?style=_shields_test')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu/buildhistory')
-    .reply(200, {results: [{status: -1}]})
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu/buildhistory')
+      .reply(200, { results: [{ status: -1 }] })
   )
-  .expectJSON({name: 'docker build', value: 'failing', colorB: colorsB.red});
+  .expectJSON({ name: 'docker build', value: 'failing', colorB: colorsB.red })
 
 t.create('docker build status (building)')
   .get('/build/_/ubuntu.json?style=_shields_test')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu/buildhistory')
-    .reply(200, {results: [{status: 1}]})
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu/buildhistory')
+      .reply(200, { results: [{ status: 1 }] })
   )
-  .expectJSON({name: 'docker build', value: 'building', colorB: '#066da5'});
+  .expectJSON({ name: 'docker build', value: 'building', colorB: '#066da5' })
 
 t.create('docker build status (override colorB for passing)')
   .get('/build/_/ubuntu.json?colorB=fedcba&style=_shields_test')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu/buildhistory')
-    .reply(200, {results: [{status: 10}]})
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu/buildhistory')
+      .reply(200, { results: [{ status: 10 }] })
   )
-  .expectJSON({name: 'docker build', value: 'passing', colorB: '#fedcba'});
+  .expectJSON({ name: 'docker build', value: 'passing', colorB: '#fedcba' })
 
 t.create('docker build status (override colorB for failing)')
   .get('/build/_/ubuntu.json?colorB=fedcba&style=_shields_test')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu/buildhistory')
-    .reply(200, {results: [{status: -1}]})
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu/buildhistory')
+      .reply(200, { results: [{ status: -1 }] })
   )
-  .expectJSON({name: 'docker build', value: 'failing', colorB: '#fedcba'});
+  .expectJSON({ name: 'docker build', value: 'failing', colorB: '#fedcba' })
 
 t.create('docker build status (override colorB for building)')
   .get('/build/_/ubuntu.json?colorB=fedcba&style=_shields_test')
-  .intercept(nock => nock('https://registry.hub.docker.com/')
-    .get('/v2/repositories/library/ubuntu/buildhistory')
-    .reply(200, {results: [{status: 1}]})
+  .intercept(nock =>
+    nock('https://registry.hub.docker.com/')
+      .get('/v2/repositories/library/ubuntu/buildhistory')
+      .reply(200, { results: [{ status: 1 }] })
   )
-  .expectJSON({name: 'docker build', value: 'building', colorB: '#fedcba'});
+  .expectJSON({ name: 'docker build', value: 'building', colorB: '#fedcba' })
diff --git a/services/dotnetstatus/dotnetstatus.tester.js b/services/dotnetstatus/dotnetstatus.tester.js
index 1580d1fdcbbfbd4a3cd26cc949b3bd75791a4686..66dd1090e242e8fdd224a40181e62a129b895df6 100644
--- a/services/dotnetstatus/dotnetstatus.tester.js
+++ b/services/dotnetstatus/dotnetstatus.tester.js
@@ -1,13 +1,13 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'dotnetstatus', title: 'dotnet-status' });
-module.exports = t;
+const t = new ServiceTester({ id: 'dotnetstatus', title: 'dotnet-status' })
+module.exports = t
 
 t.create('no longer available (previously get package status)')
   .get('/gh/jaredcnance/dotnet-status/API.json')
   .expectJSON({
     name: 'dotnet status',
-    value: 'no longer available'
-  });
+    value: 'no longer available',
+  })
diff --git a/services/dub/dub.tester.js b/services/dub/dub.tester.js
index b140d96209514a699d090a703ef97469f87c8052..310d21b25600ca6876f73e403cc6067549e6a37a 100644
--- a/services/dub/dub.tester.js
+++ b/services/dub/dub.tester.js
@@ -1,124 +1,137 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const { invalidJSON } = require('../response-fixtures');
-const colorscheme = require('../../lib/colorscheme.json');
+const { invalidJSON } = require('../response-fixtures')
+const colorscheme = require('../../lib/colorscheme.json')
 
 const {
   isVPlusDottedVersionNClausesWithOptionalSuffix,
   isMetric,
-  isMetricOverTimePeriod
-} = require('../test-validators');
+  isMetricOverTimePeriod,
+} = require('../test-validators')
 const isVersionColor = Joi.equal(
   colorscheme.red.colorB,
   colorscheme.yellow.colorB,
   colorscheme.yellowgreen.colorB,
   colorscheme.green.colorB,
   colorscheme.brightgreen.colorB
-);
-
-const t = new ServiceTester({ id: 'dub', title: 'Dub' });
-module.exports = t;
+)
 
+const t = new ServiceTester({ id: 'dub', title: 'Dub' })
+module.exports = t
 
 // downloads
 
 t.create('total downloads (valid)')
   .get('/dt/vibe-d.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric,
-    colorB: isVersionColor
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+      colorB: isVersionColor,
+    })
+  )
 
 t.create('total downloads, specific version (valid)')
   .get('/dt/vibe-d/0.7.27.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: Joi.string().regex(/^[1-9][0-9]*[kMGTPEZY]? v0.7.27$/),
-    colorB: isVersionColor
-  }))
-  .timeout(15000);
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: Joi.string().regex(/^[1-9][0-9]*[kMGTPEZY]? v0.7.27$/),
+      colorB: isVersionColor,
+    })
+  )
+  .timeout(15000)
 
 t.create('total downloads, latest version (valid)')
   .get('/dt/vibe-d/latest.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: Joi.string().regex(/^[1-9][0-9]*[kMGTPEZY]? latest$/),
-    colorB: isVersionColor
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: Joi.string().regex(/^[1-9][0-9]*[kMGTPEZY]? latest$/),
+      colorB: isVersionColor,
+    })
+  )
 
 t.create('daily downloads (valid)')
   .get('/dd/vibe-d.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriod,
-    colorB: isVersionColor
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriod,
+      colorB: isVersionColor,
+    })
+  )
 
 t.create('weekly downloads (valid)')
   .get('/dw/vibe-d.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriod,
-    colorB: isVersionColor
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriod,
+      colorB: isVersionColor,
+    })
+  )
 
 t.create('monthly downloads (valid)')
   .get('/dm/vibe-d.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriod,
-    colorB: isVersionColor
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriod,
+      colorB: isVersionColor,
+    })
+  )
 
 t.create('total downloads (not found)')
   .get('/dt/not-a-package.json')
-  .expectJSON({name: 'dub', value: 'not found'});
+  .expectJSON({ name: 'dub', value: 'not found' })
 
 t.create('total downloads (connection error)')
   .get('/dt/vibe-d.json')
   .networkOff()
-  .expectJSON({name: 'dub', value: 'inaccessible'});
+  .expectJSON({ name: 'dub', value: 'inaccessible' })
 
 t.create('total downloads (unexpected response)')
   .get('/dt/vibe-d.json')
-  .intercept(nock => nock('https://code.dlang.org')
-    .get('/api/packages/vibe-d/stats')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://code.dlang.org')
+      .get('/api/packages/vibe-d/stats')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'dub', value: 'invalid'});
-
+  .expectJSON({ name: 'dub', value: 'invalid' })
 
 // version
 
 t.create('version (valid)')
   .get('/v/vibe-d.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'dub',
-    value: isVPlusDottedVersionNClausesWithOptionalSuffix,
-    colorB: Joi.equal(colorscheme.blue.colorB, colorscheme.orange.colorB)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'dub',
+      value: isVPlusDottedVersionNClausesWithOptionalSuffix,
+      colorB: Joi.equal(colorscheme.blue.colorB, colorscheme.orange.colorB),
+    })
+  )
 
 t.create('version (not found)')
   .get('/v/not-a-package.json')
-  .expectJSON({name: 'dub', value: 'not found'});
+  .expectJSON({ name: 'dub', value: 'not found' })
 
 t.create('version (connection error)')
   .get('/v/vibe-d.json')
   .networkOff()
-  .expectJSON({name: 'dub', value: 'inaccessible'});
+  .expectJSON({ name: 'dub', value: 'inaccessible' })
 
 t.create('version (unexpected response)')
   .get('/v/vibe-d.json')
-  .intercept(nock => nock('https://code.dlang.org')
-    .get('/api/packages/vibe-d/latest')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://code.dlang.org')
+      .get('/api/packages/vibe-d/latest')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'dub', value: 'invalid'});
-
+  .expectJSON({ name: 'dub', value: 'invalid' })
 
 // license
 
@@ -127,22 +140,23 @@ t.create('license (valid)')
   .expectJSON({
     name: 'license',
     value: 'MIT',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('license (not found)')
   .get('/l/not-a-package.json')
-  .expectJSON({name: 'dub', value: 'not found'});
+  .expectJSON({ name: 'dub', value: 'not found' })
 
 t.create('license (connection error)')
   .get('/l/vibe-d.json')
   .networkOff()
-  .expectJSON({name: 'dub', value: 'inaccessible'});
+  .expectJSON({ name: 'dub', value: 'inaccessible' })
 
 t.create('license (unexpected response)')
   .get('/l/vibe-d.json')
-  .intercept(nock => nock('https://code.dlang.org')
-    .get('/api/packages/vibe-d/latest/info')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://code.dlang.org')
+      .get('/api/packages/vibe-d/latest/info')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'dub', value: 'invalid'});
+  .expectJSON({ name: 'dub', value: 'invalid' })
diff --git a/services/eclipse-marketplace/eclipse-marketplace.tester.js b/services/eclipse-marketplace/eclipse-marketplace.tester.js
index 56504f8cd7bcff989709f719d0da1987e9e28745..c90a06437076be434829fa55b77dabc0273e3f3e 100644
--- a/services/eclipse-marketplace/eclipse-marketplace.tester.js
+++ b/services/eclipse-marketplace/eclipse-marketplace.tester.js
@@ -1,48 +1,60 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
-    isFormattedDate,
-	  isMetric,
-	  isMetricOverTimePeriod,
-	  isVPlusDottedVersionAtLeastOne
-} = require('../test-validators');
+  isFormattedDate,
+  isMetric,
+  isMetricOverTimePeriod,
+  isVPlusDottedVersionAtLeastOne,
+} = require('../test-validators')
 
-const t = new ServiceTester({ id: 'eclipse-marketplace', title: 'Eclipse' });
-module.exports = t;
+const t = new ServiceTester({ id: 'eclipse-marketplace', title: 'Eclipse' })
+module.exports = t
 
 t.create('total marketplace downloads')
   .get('/dt/notepad4e.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('monthly marketplace downloads')
   .get('/dm/notepad4e.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriod,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriod,
+    })
+  )
 
 t.create('marketplace version')
   .get('/v/notepad4e.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'eclipse marketplace',
-    value: isVPlusDottedVersionAtLeastOne,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'eclipse marketplace',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('favorites count')
   .get('/favorites/notepad4e.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'favorites',
-    value: Joi.number().integer().positive(),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'favorites',
+      value: Joi.number()
+        .integer()
+        .positive(),
+    })
+  )
 
 t.create('last update date')
   .get('/last-update/notepad4e.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'updated',
-    value: isFormattedDate,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'updated',
+      value: isFormattedDate,
+    })
+  )
diff --git a/services/elm-package/elm-package.tester.js b/services/elm-package/elm-package.tester.js
index 392163b626e0698b28e17ca0972f4a64d874d795..3fed5cafc878eee85dbbca8e03fa91c05d0aeaf4 100644
--- a/services/elm-package/elm-package.tester.js
+++ b/services/elm-package/elm-package.tester.js
@@ -1,16 +1,16 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isSemver } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isSemver } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'elm-package', title: 'ELM PACKAGE' });
-module.exports = t;
+const t = new ServiceTester({ id: 'elm-package', title: 'ELM PACKAGE' })
+module.exports = t
 
 t.create('gets the package version of elm-lang/core')
   .get('/v/elm-lang/core.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'elm-package', value: isSemver }));
+  .expectJSONTypes(Joi.object().keys({ name: 'elm-package', value: isSemver }))
 
 t.create('invalid package name')
   .get('/v/elm-community/frodo-is-not-a-package.json')
-  .expectJSON({ name: 'elm-package', value: 'invalid' });
+  .expectJSON({ name: 'elm-package', value: 'invalid' })
diff --git a/services/errors.js b/services/errors.js
index 61fc9de89a5c62c195c8e4d01a891ee69d117902..68131efc35837c01b57ba0d669958bb4539544e0 100644
--- a/services/errors.js
+++ b/services/errors.js
@@ -1,59 +1,71 @@
-'use strict';
+'use strict'
 
 class ShieldsRuntimeError extends Error {
-
-  get name() { return 'ShieldsRuntimeError'; }
-  get defaultPrettyMessage() { throw new Error('Must implement abstract method'); }
+  get name() {
+    return 'ShieldsRuntimeError'
+  }
+  get defaultPrettyMessage() {
+    throw new Error('Must implement abstract method')
+  }
 
   constructor(props = {}, message) {
-    super(message);
-    this.prettyMessage = props.prettyMessage || this.defaultPrettyMessage;
+    super(message)
+    this.prettyMessage = props.prettyMessage || this.defaultPrettyMessage
     if (props.underlyingError) {
-      this.stack = props.underlyingError.stack;
+      this.stack = props.underlyingError.stack
     }
   }
 }
 
-
-const defaultNotFoundError = 'not found';
+const defaultNotFoundError = 'not found'
 
 class NotFound extends ShieldsRuntimeError {
-
-  get name() { return 'NotFound'; }
-  get defaultPrettyMessage() { return defaultNotFoundError; }
+  get name() {
+    return 'NotFound'
+  }
+  get defaultPrettyMessage() {
+    return defaultNotFoundError
+  }
 
   constructor(props = {}) {
-    const prettyMessage = props.prettyMessage || defaultNotFoundError;
-    const message = prettyMessage === defaultNotFoundError
-      ? 'Not Found'
-      : `Not Found: ${prettyMessage}`;
-    super(props, message);
+    const prettyMessage = props.prettyMessage || defaultNotFoundError
+    const message =
+      prettyMessage === defaultNotFoundError
+        ? 'Not Found'
+        : `Not Found: ${prettyMessage}`
+    super(props, message)
   }
 }
 
 class InvalidResponse extends ShieldsRuntimeError {
-
-  get name() { return 'InvalidResponse'; }
-  get defaultPrettyMessage() { return 'invalid'; }
+  get name() {
+    return 'InvalidResponse'
+  }
+  get defaultPrettyMessage() {
+    return 'invalid'
+  }
 
   constructor(props = {}) {
     const message = props.underlyingError
       ? `Invalid Response: ${props.underlyingError.message}`
-      : 'Invalid Response';
-    super(props, message);
+      : 'Invalid Response'
+    super(props, message)
   }
 }
 
 class Inaccessible extends ShieldsRuntimeError {
-
-  get name() { return 'Inaccessible'; }
-  get defaultPrettyMessage() { return 'inaccessible'; }
+  get name() {
+    return 'Inaccessible'
+  }
+  get defaultPrettyMessage() {
+    return 'inaccessible'
+  }
 
   constructor(props = {}) {
     const message = props.underlyingError
       ? `Inaccessible: ${props.underlyingError.message}`
-      : 'Inaccessible';
-    super(props, message);
+      : 'Inaccessible'
+    super(props, message)
   }
 }
 
@@ -61,4 +73,4 @@ module.exports = {
   NotFound,
   InvalidResponse,
   Inaccessible,
-};
+}
diff --git a/services/gem/gem.service.js b/services/gem/gem.service.js
index 54032a8f9aa445a8980184652d095d59901add7d..03a9033b6813f29b50b86a697d704d8df9ab7666 100644
--- a/services/gem/gem.service.js
+++ b/services/gem/gem.service.js
@@ -1,51 +1,47 @@
-'use strict';
+'use strict'
 
-const semver = require('semver');
-const Joi = require('joi');
+const semver = require('semver')
+const Joi = require('joi')
 
-const { BaseJsonService } = require('../base');
-const { InvalidResponse } = require('../errors');
-const { addv: versionText } = require('../../lib/text-formatters');
-const { version: versionColor} = require('../../lib/color-formatters');
+const { BaseJsonService } = require('../base')
+const { InvalidResponse } = require('../errors')
+const { addv: versionText } = require('../../lib/text-formatters')
+const { version: versionColor } = require('../../lib/color-formatters')
 const {
   floorCount: floorCountColor,
   downloadCount: downloadCountColor,
-} = require('../../lib/color-formatters');
-const {
-  metric,
-  ordinalNumber,
-} = require('../../lib/text-formatters');
-const { latest: latestVersion } = require('../../lib/version');
-
+} = require('../../lib/color-formatters')
+const { metric, ordinalNumber } = require('../../lib/text-formatters')
+const { latest: latestVersion } = require('../../lib/version')
 
 class GemVersion extends BaseJsonService {
-  async handle({repo}) {
-    const url = `https://rubygems.org/api/v1/gems/${repo}.json`;
+  async handle({ repo }) {
+    const url = `https://rubygems.org/api/v1/gems/${repo}.json`
     const { version } = await this._requestJson({
       url,
       schema: Joi.object(),
-    });
+    })
     return {
       message: versionText(version),
-      color: versionColor(version)
-    };
+      color: versionColor(version),
+    }
   }
 
   // Metadata
   static get defaultBadgeData() {
-    return { label: 'gem' };
+    return { label: 'gem' }
   }
 
   static get category() {
-    return 'version';
+    return 'version'
   }
 
   static get url() {
     return {
       base: 'gem/v',
       format: '(.+)',
-      capture: ['repo']
-    };
+      capture: ['repo'],
+    }
   }
 
   static get examples() {
@@ -53,106 +49,103 @@ class GemVersion extends BaseJsonService {
       {
         title: 'Gem',
         previewUrl: 'formatador',
-        keywords: [
-          'ruby'
-        ]
-      }
-    ];
+        keywords: ['ruby'],
+      },
+    ]
   }
-};
+}
 
 class GemDownloads extends BaseJsonService {
-
   fetch(repo, info) {
-    const endpoint = info === "dv" ? 'versions/' : 'gems/';
-    const url = `https://rubygems.org/api/v1/${endpoint}${repo}.json`;
+    const endpoint = info === 'dv' ? 'versions/' : 'gems/'
+    const url = `https://rubygems.org/api/v1/${endpoint}${repo}.json`
     return this._requestJson({
       url,
       schema: Joi.any(),
-    });
+    })
   }
 
   _getLabel(version, info) {
     if (version) {
-      return 'downloads@' + version;
+      return 'downloads@' + version
     } else {
-      if (info === "dtv") {
-        return 'downloads@latest';
+      if (info === 'dtv') {
+        return 'downloads@latest'
       } else {
-        return 'downloads';
+        return 'downloads'
       }
     }
   }
 
-  async handle({info, rubygem}) {
-    const splitRubygem = rubygem.split('/');
-    const repo = splitRubygem[0];
-    let version = (splitRubygem.length > 1)
-      ? splitRubygem[splitRubygem.length - 1]
-      : null;
-    version = (version === "stable") ? version : semver.valid(version);
-    const label = this._getLabel(version, info);
-    const json = await this.fetch(repo, info);
-
-    let downloads;
-    if (info === "dt") {
-      downloads = metric(json.downloads);
-    } else if (info === "dtv") {
-      downloads = metric(json.version_downloads);
-    } else if (info === "dv") {
-
-      let versionData;
-      if (version !== null && version === "stable") {
-
-        const versions = json.filter(function(ver) {
-          return ver.prerelease === false;
-        }).map(function(ver) {
-          return ver.number;
-        });
+  async handle({ info, rubygem }) {
+    const splitRubygem = rubygem.split('/')
+    const repo = splitRubygem[0]
+    let version =
+      splitRubygem.length > 1 ? splitRubygem[splitRubygem.length - 1] : null
+    version = version === 'stable' ? version : semver.valid(version)
+    const label = this._getLabel(version, info)
+    const json = await this.fetch(repo, info)
+
+    let downloads
+    if (info === 'dt') {
+      downloads = metric(json.downloads)
+    } else if (info === 'dtv') {
+      downloads = metric(json.version_downloads)
+    } else if (info === 'dv') {
+      let versionData
+      if (version !== null && version === 'stable') {
+        const versions = json
+          .filter(function(ver) {
+            return ver.prerelease === false
+          })
+          .map(function(ver) {
+            return ver.number
+          })
         // Found latest stable version.
-        const stableVersion = latestVersion(versions);
+        const stableVersion = latestVersion(versions)
         versionData = json.filter(function(ver) {
-          return ver.number === stableVersion;
-        })[0];
-        downloads = metric(versionData.downloads_count);
-
+          return ver.number === stableVersion
+        })[0]
+        downloads = metric(versionData.downloads_count)
       } else if (version !== null) {
-
         versionData = json.filter(function(ver) {
-          return ver.number === version;
-        })[0];
+          return ver.number === version
+        })[0]
 
-        downloads = metric(versionData.downloads_count);
+        downloads = metric(versionData.downloads_count)
       } else {
-        throw new InvalidResponse({ underlyingError: new Error('version is null') });
+        throw new InvalidResponse({
+          underlyingError: new Error('version is null'),
+        })
       }
-
     } else {
-      throw new InvalidResponse({ underlyingError: new Error('info is invalid') });
+      throw new InvalidResponse({
+        underlyingError: new Error('info is invalid'),
+      })
     }
 
     return {
       label: label,
       message: downloads,
       color: downloadCountColor(downloads),
-    };
+    }
   }
 
   // Metadata
   static get defaultBadgeData() {
-    return { label: 'downloads' };
+    return { label: 'downloads' }
   }
 
   static get category() {
-    return 'downloads';
+    return 'downloads'
   }
 
   static get url() {
     return {
       base: 'gem',
       format: '(dt|dtv|dv)/(.+)',
-      capture: ['info', 'rubygem']
-    };
+      capture: ['info', 'rubygem'],
+    }
   }
 
   static get examples() {
@@ -160,66 +153,57 @@ class GemDownloads extends BaseJsonService {
       {
         title: 'Gem',
         previewUrl: 'dv/rails/stable',
-        keywords: [
-          'ruby'
-        ]
+        keywords: ['ruby'],
       },
       {
         title: 'Gem',
         previewUrl: 'dv/rails/4.1.0',
-        keywords: [
-          'ruby'
-        ]
+        keywords: ['ruby'],
       },
       {
         title: 'Gem',
         previewUrl: 'dtv/rails',
-        keywords: [
-          'ruby'
-        ]
+        keywords: ['ruby'],
       },
       {
         title: 'Gem',
         previewUrl: 'dt/rails',
-        keywords: [
-          'ruby'
-        ]
+        keywords: ['ruby'],
       },
-    ];
+    ]
   }
-};
+}
 
 class GemOwner extends BaseJsonService {
-
-  async handle({user}) {
-    const url = `https://rubygems.org/api/v1/owners/${user}/gems.json`;
+  async handle({ user }) {
+    const url = `https://rubygems.org/api/v1/owners/${user}/gems.json`
     const json = await this._requestJson({
       url,
       schema: Joi.array(),
-    });
-    const count = json.length;
+    })
+    const count = json.length
 
     return {
       message: count,
-      color: floorCountColor(count, 10, 50, 100)
-    };
+      color: floorCountColor(count, 10, 50, 100),
+    }
   }
 
   // Metadata
   static get defaultBadgeData() {
-    return { label: 'gems' };
+    return { label: 'gems' }
   }
 
   static get category() {
-    return 'other';
+    return 'other'
   }
 
   static get url() {
     return {
       base: 'gem/u',
       format: '(.+)',
-      capture: ['user']
-    };
+      capture: ['user'],
+    }
   }
 
   static get examples() {
@@ -227,66 +211,63 @@ class GemOwner extends BaseJsonService {
       {
         title: 'Gems',
         previewUrl: 'raphink',
-        keywords: [
-          'ruby'
-        ]
-      }
-    ];
+        keywords: ['ruby'],
+      },
+    ]
   }
-};
+}
 
 class GemRank extends BaseJsonService {
-
   _getApiUrl(repo, totalRank, dailyRank) {
-    let endpoint;
+    let endpoint
     if (totalRank) {
-      endpoint = '/total_ranking.json';
+      endpoint = '/total_ranking.json'
     } else if (dailyRank) {
-      endpoint = '/daily_ranking.json';
+      endpoint = '/daily_ranking.json'
     }
-    return `http://bestgems.org/api/v1/gems/${repo}${endpoint}`;
+    return `http://bestgems.org/api/v1/gems/${repo}${endpoint}`
   }
 
-  async handle({info, repo}) {
-    const totalRank = (info === 'rt');
-    const dailyRank = (info === 'rd');
-    const url = this._getApiUrl(repo, totalRank, dailyRank);
+  async handle({ info, repo }) {
+    const totalRank = info === 'rt'
+    const dailyRank = info === 'rd'
+    const url = this._getApiUrl(repo, totalRank, dailyRank)
     const json = await this._requestJson({
       url,
       schema: Joi.array(),
-    });
+    })
 
-    let rank;
+    let rank
     if (totalRank) {
-      rank = json[0].total_ranking;
+      rank = json[0].total_ranking
     } else if (dailyRank) {
-      rank = json[0].daily_ranking;
+      rank = json[0].daily_ranking
     }
-    const count = Math.floor(100000 / rank);
-    let message = ordinalNumber(rank);
+    const count = Math.floor(100000 / rank)
+    let message = ordinalNumber(rank)
     message += totalRank ? '' : ' daily'
 
     return {
       message: message,
-      color: floorCountColor(count, 10, 50, 100)
-    };
+      color: floorCountColor(count, 10, 50, 100),
+    }
   }
 
   // Metadata
   static get defaultBadgeData() {
-    return { label: 'rank' };
+    return { label: 'rank' }
   }
 
   static get category() {
-    return 'rating';
+    return 'rating'
   }
 
   static get url() {
     return {
       base: 'gem',
       format: '(rt|rd)/(.+)',
-      capture: ['info', 'repo']
-    };
+      capture: ['info', 'repo'],
+    }
   }
 
   static get examples() {
@@ -294,20 +275,16 @@ class GemRank extends BaseJsonService {
       {
         title: 'Gems',
         previewUrl: 'rt/puppet',
-        keywords: [
-          'ruby'
-        ]
+        keywords: ['ruby'],
       },
       {
         title: 'Gems',
         previewUrl: 'rd/facter',
-        keywords: [
-          'ruby'
-        ]
-      }
-    ];
+        keywords: ['ruby'],
+      },
+    ]
   }
-};
+}
 
 module.exports = {
   GemVersion,
diff --git a/services/gem/gem.tester.js b/services/gem/gem.tester.js
index 9801f5bb62f91fe471a228518080a72ab3eb9857..6ee7d62249b275d5e20abdc7bee5a4816cfd1071 100644
--- a/services/gem/gem.tester.js
+++ b/services/gem/gem.tester.js
@@ -1,149 +1,161 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
 const {
   isVPlusDottedVersionAtLeastOne,
-  isMetric
-} = require('../test-validators');
-const isOrdinalNumber = Joi.string().regex(/^[1-9][0-9]+(ᵗʰ|ˢᵗ|ⁿᵈ|ʳᵈ)$/);
-const isOrdinalNumberDaily = Joi.string().regex(/^[1-9][0-9]+(ᵗʰ|ˢᵗ|ⁿᵈ|ʳᵈ) daily$/);
-
-const t = new ServiceTester({ id: 'gem', title: 'Ruby Gems' });
-module.exports = t;
+  isMetric,
+} = require('../test-validators')
+const isOrdinalNumber = Joi.string().regex(/^[1-9][0-9]+(ᵗʰ|ˢᵗ|ⁿᵈ|ʳᵈ)$/)
+const isOrdinalNumberDaily = Joi.string().regex(
+  /^[1-9][0-9]+(ᵗʰ|ˢᵗ|ⁿᵈ|ʳᵈ) daily$/
+)
 
+const t = new ServiceTester({ id: 'gem', title: 'Ruby Gems' })
+module.exports = t
 
 // version endpoint
 
 t.create('version (valid)')
   .get('/v/formatador.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'gem',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'gem',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('version (not found)')
   .get('/v/not-a-package.json')
-  .expectJSON({name: 'gem', value: 'not found'});
+  .expectJSON({ name: 'gem', value: 'not found' })
 
 t.create('version (connection error)')
   .get('/v/formatador.json')
   .networkOff()
-  .expectJSON({name: 'gem', value: 'inaccessible'});
-
+  .expectJSON({ name: 'gem', value: 'inaccessible' })
 
 // downloads endpoints
 
 // total downloads
 t.create('total downloads (valid)')
   .get('/dt/rails.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('total downloads (not found)')
   .get('/dt/not-a-package.json')
-  .expectJSON({name: 'downloads', value: 'not found'});
+  .expectJSON({ name: 'downloads', value: 'not found' })
 
 t.create('total downloads (connection error)')
   .get('/dt/rails.json')
   .networkOff()
-  .expectJSON({name: 'downloads', value: 'inaccessible'});
-
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 // version downloads
 t.create('version downloads (valid, stable version)')
   .get('/dv/rails/stable.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads@stable',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads@stable',
+      value: isMetric,
+    })
+  )
 
 t.create('version downloads (valid, specific version)')
   .get('/dv/rails/4.1.0.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads@4.1.0',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads@4.1.0',
+      value: isMetric,
+    })
+  )
 
 t.create('version downloads (package not found)')
   .get('/dv/not-a-package/4.1.0.json')
-  .expectJSON({name: 'downloads', value: 'not found'});
+  .expectJSON({ name: 'downloads', value: 'not found' })
 
 t.create('version downloads (valid package, invalid version)')
   .get('/dv/rails/not-a-version.json')
-  .expectJSON({name: 'downloads', value: 'invalid'});
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('version downloads (valid package, version not specified)')
   .get('/dv/rails.json')
-  .expectJSON({name: 'downloads', value: 'invalid'});
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('version downloads (connection error)')
   .get('/dv/rails/4.1.0.json')
   .networkOff()
-  .expectJSON({name: 'downloads', value: 'inaccessible'});
-
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 // latest version downloads
 t.create('latest version downloads (valid)')
   .get('/dtv/rails.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads@latest',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads@latest',
+      value: isMetric,
+    })
+  )
 
 t.create('latest version downloads (not found)')
   .get('/dtv/not-a-package.json')
-  .expectJSON({name: 'downloads', value: 'not found'});
+  .expectJSON({ name: 'downloads', value: 'not found' })
 
 t.create('latest version downloads (connection error)')
   .get('/dtv/rails.json')
   .networkOff()
-  .expectJSON({name: 'downloads', value: 'inaccessible'});
-
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 // users endpoint
 
 t.create('users (valid)')
   .get('/u/raphink.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'gems',
-    value: Joi.string().regex(/^[0-9]+$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'gems',
+      value: Joi.string().regex(/^[0-9]+$/),
+    })
+  )
 
 t.create('users (not found)')
   .get('/u/not-a-package.json')
-  .expectJSON({name: 'gems', value: 'not found'});
+  .expectJSON({ name: 'gems', value: 'not found' })
 
 t.create('users (connection error)')
   .get('/u/raphink.json')
   .networkOff()
-  .expectJSON({name: 'gems', value: 'inaccessible'});
-
+  .expectJSON({ name: 'gems', value: 'inaccessible' })
 
 // rank endpoint
 
 t.create('total rank (valid)')
   .get('/rt/rspec-puppet-facts.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'rank',
-    value: isOrdinalNumber
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rank',
+      value: isOrdinalNumber,
+    })
+  )
 
 t.create('daily rank (valid)')
   .get('/rd/rspec-puppet-facts.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'rank',
-    value: isOrdinalNumberDaily
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rank',
+      value: isOrdinalNumberDaily,
+    })
+  )
 
 t.create('rank (not found)')
   .get('/rt/not-a-package.json')
-  .expectJSON({name: 'rank', value: 'not found'});
+  .expectJSON({ name: 'rank', value: 'not found' })
 
 t.create('rank (connection error)')
   .get('/rt/rspec-puppet-facts.json')
   .networkOff()
-  .expectJSON({name: 'rank', value: 'inaccessible'});
+  .expectJSON({ name: 'rank', value: 'inaccessible' })
diff --git a/services/gemnasium/gemnasium.tester.js b/services/gemnasium/gemnasium.tester.js
index 21c064626441beee614518bb3225cf30fef4e99c..6f23ffa235e5d96460f191028151b9aaa2f9fb29 100644
--- a/services/gemnasium/gemnasium.tester.js
+++ b/services/gemnasium/gemnasium.tester.js
@@ -1,21 +1,20 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
+const ServiceTester = require('../service-tester')
 const { expect } = require('chai')
 
-const { isDeprecated } = require('../../lib/deprecation-helpers');
-
-const t = new ServiceTester({ id: 'gemnasium', title: 'gemnasium' });
-module.exports = t;
+const { isDeprecated } = require('../../lib/deprecation-helpers')
 
+const t = new ServiceTester({ id: 'gemnasium', title: 'gemnasium' })
+module.exports = t
 
 t.create('no longer available (previously dependencies)')
   .get('/mathiasbynens/he.json')
   .afterJSON(function(badge) {
     if (isDeprecated('gemnasium')) {
-      expect(badge.name).to.equal('gemnasium');
-      expect(badge.value).to.equal('no longer available');
+      expect(badge.name).to.equal('gemnasium')
+      expect(badge.value).to.equal('no longer available')
     } else {
-      expect(badge.name).to.equal('dependencies');
+      expect(badge.name).to.equal('dependencies')
     }
-  });
+  })
diff --git a/services/github/auth/admin.js b/services/github/auth/admin.js
index 7a7ee054bab9a1a211ce8b349b5946255e4d8583..01f1d0265ea9cd467bf7c5accf259d2be1cf512e 100644
--- a/services/github/auth/admin.js
+++ b/services/github/auth/admin.js
@@ -1,8 +1,8 @@
-'use strict';
+'use strict'
 
-const crypto = require('crypto');
-const { serializeDebugInfo } = require('../../../lib/github-auth');
-const serverSecrets = require('../../../lib/server-secrets');
+const crypto = require('crypto')
+const { serializeDebugInfo } = require('../../../lib/github-auth')
+const serverSecrets = require('../../../lib/server-secrets')
 
 function setRoutes(server) {
   // Allow the admin to obtain the tokens for operational and debugging
@@ -21,13 +21,13 @@ function setRoutes(server) {
     if (!crypto.timingSafeEqual(ask.password, serverSecrets.shieldsSecret)) {
       // An unknown entity tries to connect. Let the connection linger for a minute.
       return setTimeout(function() {
-        end('Invalid secret.');
-      }, 10000);
+        end('Invalid secret.')
+      }, 10000)
     }
-    end(serializeDebugInfo({ sanitize: false }));
-  });
+    end(serializeDebugInfo({ sanitize: false }))
+  })
 }
 
 module.exports = {
   setRoutes,
-};
+}
diff --git a/services/github/github-api-provider.integration.js b/services/github/github-api-provider.integration.js
index d584bedab180a042ce0f68fd95e5aeaa43df2728..27e72cf4d49029ca4335af1ca711538cf09f3bd0 100644
--- a/services/github/github-api-provider.integration.js
+++ b/services/github/github-api-provider.integration.js
@@ -1,37 +1,37 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const GithubApiProvider = require('./github-api-provider');
+const { expect } = require('chai')
+const GithubApiProvider = require('./github-api-provider')
 
 describe('Github API provider', function() {
-  const baseUrl = process.env.GITHUB_URL || 'https://api.github.com';
+  const baseUrl = process.env.GITHUB_URL || 'https://api.github.com'
 
-  let githubApiProvider;
+  let githubApiProvider
   before(function() {
-    githubApiProvider = new GithubApiProvider({ baseUrl });
-  });
+    githubApiProvider = new GithubApiProvider({ baseUrl })
+  })
 
-  const headers = [];
+  const headers = []
   async function performOneRequest() {
     const { res } = await githubApiProvider.requestAsPromise(
       require('request'),
       '/repos/rust-lang/rust',
       {}
-    );
-    expect(res.statusCode).to.equal(200);
-    headers.push(res.headers);
+    )
+    expect(res.statusCode).to.equal(200)
+    headers.push(res.headers)
   }
 
   before('should be able to run 10 requests', async function() {
-    this.timeout(10000);
+    this.timeout(10000)
     for (let i = 0; i < 10; ++i) {
-      await performOneRequest();
+      await performOneRequest()
     }
-  });
+  })
 
   it('should decrement the limit remaining with each request', function() {
-    const remaining = headers.map(h => +h['x-ratelimit-remaining']);
-    const expected = Array.from({ length: 10 }, (e, i) => remaining[0] - i);
-    expect(remaining).to.deep.equal(expected);
-  });
-});
+    const remaining = headers.map(h => +h['x-ratelimit-remaining'])
+    const expected = Array.from({ length: 10 }, (e, i) => remaining[0] - i)
+    expect(remaining).to.deep.equal(expected)
+  })
+})
diff --git a/services/github/github-api-provider.js b/services/github/github-api-provider.js
index b0f6f49e6c3106df3a8d0ee34d34ac44ee7ece01..ef6aac2231c4f1ce20be54a4ff55b4940e75232d 100644
--- a/services/github/github-api-provider.js
+++ b/services/github/github-api-provider.js
@@ -1,6 +1,6 @@
-'use strict';
+'use strict'
 
-const githubAuth = require('../../lib/github-auth');
+const githubAuth = require('../../lib/github-auth')
 
 // Provide an interface to the Github API. Manages the base URL.
 //
@@ -9,36 +9,36 @@ const githubAuth = require('../../lib/github-auth');
 // to legacy code.
 class GithubApiProvider {
   constructor({ baseUrl }) {
-    this.baseUrl = baseUrl;
+    this.baseUrl = baseUrl
   }
 
   // Act like request(), but tweak headers and query to avoid hitting a rate
   // limit. Inject `request` so we can pass in `cachingRequest` from
   // `request-handler.js`.
   request(request, url, query, callback) {
-    const { baseUrl } = this;
+    const { baseUrl } = this
 
     githubAuth.request(
       request,
       `${baseUrl}${url}`,
       query,
       (err, res, buffer) => {
-        callback(err, res, buffer);
+        callback(err, res, buffer)
       }
-    );
+    )
   }
 
   requestAsPromise(request, url, query) {
     return new Promise((resolve, reject) => {
       this.request(request, url, query, (err, res, buffer) => {
         if (err) {
-          reject(err);
+          reject(err)
         } else {
-          resolve({ res, buffer });
+          resolve({ res, buffer })
         }
-      });
-    });
+      })
+    })
   }
 }
 
-module.exports = GithubApiProvider;
+module.exports = GithubApiProvider
diff --git a/services/github/github-api-provider.spec.js b/services/github/github-api-provider.spec.js
index 334652dabffed9154855971f709145933ad8e0b9..94b61d4544c17f26a19c3170b19ef9983833b354 100644
--- a/services/github/github-api-provider.spec.js
+++ b/services/github/github-api-provider.spec.js
@@ -1,20 +1,20 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const GithubApiProvider = require('./github-api-provider');
+const { expect } = require('chai')
+const GithubApiProvider = require('./github-api-provider')
 
 describe('Github API provider', function() {
-  const baseUrl = 'https://github-api.example.com';
+  const baseUrl = 'https://github-api.example.com'
 
-  let provider;
+  let provider
   beforeEach(function() {
-    provider = new GithubApiProvider({ baseUrl });
-  });
+    provider = new GithubApiProvider({ baseUrl })
+  })
 
   context('a valid response', function() {
-    const rateLimit = 12500;
-    const remaining = 7955;
-    const nextReset = 123456789;
+    const rateLimit = 12500
+    const remaining = 7955
+    const nextReset = 123456789
     const mockResponse = {
       statusCode: 200,
       headers: {
@@ -22,52 +22,52 @@ describe('Github API provider', function() {
         'x-ratelimit-remaining': remaining,
         'x-ratelimit-reset': nextReset,
       },
-    };
-    const mockBuffer = Buffer.alloc(0);
+    }
+    const mockBuffer = Buffer.alloc(0)
     const mockRequest = (...args) => {
-      const callback = args.pop();
-      callback(null, mockResponse, mockBuffer);
-    };
+      const callback = args.pop()
+      callback(null, mockResponse, mockBuffer)
+    }
 
     it('should invoke the callback', function(done) {
       provider.request(mockRequest, '/foo', {}, (err, res, buffer) => {
-        expect(err).to.equal(null);
-        expect(Object.is(res, mockResponse)).to.be.true;
-        expect(Object.is(buffer, mockBuffer)).to.be.true;
-        done();
-      });
-    });
-  });
+        expect(err).to.equal(null)
+        expect(Object.is(res, mockResponse)).to.be.true
+        expect(Object.is(buffer, mockBuffer)).to.be.true
+        done()
+      })
+    })
+  })
 
   context('an unauthorized response', function() {
-    const mockResponse = { statusCode: 401 };
-    const mockBuffer = Buffer.alloc(0);
+    const mockResponse = { statusCode: 401 }
+    const mockBuffer = Buffer.alloc(0)
     const mockRequest = (...args) => {
-      const callback = args.pop();
-      callback(null, mockResponse, mockBuffer);
-    };
+      const callback = args.pop()
+      callback(null, mockResponse, mockBuffer)
+    }
 
     it('should invoke the callback', function(done) {
       provider.request(mockRequest, '/foo', {}, (err, res, buffer) => {
-        expect(err).to.equal(null);
+        expect(err).to.equal(null)
         // Add more?
-        done();
-      });
-    });
-  });
+        done()
+      })
+    })
+  })
 
   context('a connection error', function() {
     const mockRequest = (...args) => {
-      const callback = args.pop();
-      callback(Error('connection timeout'));
-    };
+      const callback = args.pop()
+      callback(Error('connection timeout'))
+    }
 
     it('should pass the error to the callback', function(done) {
       provider.request(mockRequest, '/foo', {}, (err, res, buffer) => {
-        expect(err).to.be.an.instanceof(Error);
-        expect(err.message).to.equal('connection timeout');
-        done();
-      });
-    });
-  });
-});
+        expect(err).to.be.an.instanceof(Error)
+        expect(err.message).to.equal('connection timeout')
+        done()
+      })
+    })
+  })
+})
diff --git a/services/github/github.tester.js b/services/github/github.tester.js
index 42af7fa63909276a552978339f802d075c74afeb..6b030372b8179deb87459a9af178f95432f6bcdf 100644
--- a/services/github/github.tester.js
+++ b/services/github/github.tester.js
@@ -1,719 +1,902 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isMetric,
   isMetricOpenIssues,
   isMetricOverTimePeriod,
   isFileSize,
   isFormattedDate,
-  isVPlusDottedVersionAtLeastOne
-} = require('../test-validators');
-const colorscheme = require('../../lib/colorscheme.json');
-const {licenseToColor} = require('../../lib/licenses');
-const {makeColor} = require('../../lib/badge-data');
-const mapValues = require('lodash.mapvalues');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'github', title: 'Github' });
-module.exports = t;
-const colorsB = mapValues(colorscheme, 'colorB');
-const publicDomainLicenseColor = makeColor(licenseToColor('CC0-1.0'));
-const permissiveLicenseColor = colorsB[licenseToColor('MIT')];
-const copyleftLicenseColor = colorsB[licenseToColor('GPL-3.0')];
-const unknownLicenseColor = colorsB[licenseToColor()];
+  isVPlusDottedVersionAtLeastOne,
+} = require('../test-validators')
+const colorscheme = require('../../lib/colorscheme.json')
+const { licenseToColor } = require('../../lib/licenses')
+const { makeColor } = require('../../lib/badge-data')
+const mapValues = require('lodash.mapvalues')
+const { invalidJSON } = require('../response-fixtures')
+
+const t = new ServiceTester({ id: 'github', title: 'Github' })
+module.exports = t
+const colorsB = mapValues(colorscheme, 'colorB')
+const publicDomainLicenseColor = makeColor(licenseToColor('CC0-1.0'))
+const permissiveLicenseColor = colorsB[licenseToColor('MIT')]
+const copyleftLicenseColor = colorsB[licenseToColor('GPL-3.0')]
+const unknownLicenseColor = colorsB[licenseToColor()]
 
 t.create('Public domain license')
   .get('/license/github/gitignore.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'CC0-1.0', colorB: publicDomainLicenseColor });
+  .expectJSON({
+    name: 'license',
+    value: 'CC0-1.0',
+    colorB: publicDomainLicenseColor,
+  })
 
 t.create('Copyleft license')
   .get('/license/ansible/ansible.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'GPL-3.0', colorB: copyleftLicenseColor });
+  .expectJSON({
+    name: 'license',
+    value: 'GPL-3.0',
+    colorB: copyleftLicenseColor,
+  })
 
 t.create('Permissive license')
   .get('/license/atom/atom.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'MIT', colorB: permissiveLicenseColor });
+  .expectJSON({ name: 'license', value: 'MIT', colorB: permissiveLicenseColor })
 
 t.create('License for repo without a license')
   .get('/license/badges/badger.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'missing', colorB: colorsB.red });
+  .expectJSON({ name: 'license', value: 'missing', colorB: colorsB.red })
 
 t.create('License for repo with an unrecognized license')
   .get('/license/philokev/sopel-noblerealms.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'unknown', colorB: unknownLicenseColor });
+  .expectJSON({
+    name: 'license',
+    value: 'unknown',
+    colorB: unknownLicenseColor,
+  })
 
 t.create('License with SPDX id not appearing in configuration')
   .get('/license/user1/project-with-EFL-license.json?style=_shields_test')
-  .intercept(nock => nock('https://api.github.com')
-    .get('/repos/user1/project-with-EFL-license')
-    .query(true)
-    // GitHub API currently returns "other" as a key for repo with EFL license
-    .reply(200, {
-      license: {
-        key: 'efl-1.0',
-        name: 'Eiffel Forum License v1.0',
-        spdx_id: 'EFL-1.0',
-        url: 'https://api.github.com/licenses/efl-1.0',
-        featured: true
-      }
-    }))
-  .expectJSON({ name: 'license', value: 'EFL-1.0', colorB: unknownLicenseColor });
+  .intercept(nock =>
+    nock('https://api.github.com')
+      .get('/repos/user1/project-with-EFL-license')
+      .query(true)
+      // GitHub API currently returns "other" as a key for repo with EFL license
+      .reply(200, {
+        license: {
+          key: 'efl-1.0',
+          name: 'Eiffel Forum License v1.0',
+          spdx_id: 'EFL-1.0',
+          url: 'https://api.github.com/licenses/efl-1.0',
+          featured: true,
+        },
+      })
+  )
+  .expectJSON({
+    name: 'license',
+    value: 'EFL-1.0',
+    colorB: unknownLicenseColor,
+  })
 
 t.create('License for unknown repo')
   .get('/license/user1/github-does-not-have-this-repo.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'repo not found', colorB: colorsB.lightgrey });
+  .expectJSON({
+    name: 'license',
+    value: 'repo not found',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('License - API rate limit exceeded')
   .get('/license/user1/repo1.json?style=_shields_test')
-  .intercept(nock => nock('https://api.github.com')
-    .get('/repos/user1/repo1')
-    .query(true)
-    .reply(403, {
-      message: "API rate limit exceeded for 123.123.123.123. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
-      documentation_url: "https://developer.github.com/v3/#rate-limiting"
-  }))
-  .expectJSON({ name: 'license', value: 'invalid', colorB: colorsB.lightgrey });
+  .intercept(nock =>
+    nock('https://api.github.com')
+      .get('/repos/user1/repo1')
+      .query(true)
+      .reply(403, {
+        message:
+          "API rate limit exceeded for 123.123.123.123. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
+        documentation_url: 'https://developer.github.com/v3/#rate-limiting',
+      })
+  )
+  .expectJSON({ name: 'license', value: 'invalid', colorB: colorsB.lightgrey })
 
 t.create('Contributors')
   .get('/contributors/cdnjs/cdnjs.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'contributors',
-    value: Joi.string().regex(/^\w+$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'contributors',
+      value: Joi.string().regex(/^\w+$/),
+    })
+  )
 
 t.create('Contributors (repo not found)')
   .get('/contributors/badges/helmets.json')
   .expectJSON({
     name: 'contributors',
-    value: 'repo not found'
-  });
+    value: 'repo not found',
+  })
 
 t.create('GitHub closed pull requests')
   .get('/issues-pr-closed/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'pull requests',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? closed$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'pull requests',
+      value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? closed$/),
+    })
+  )
 
 t.create('GitHub closed pull requests raw')
   .get('/issues-pr-closed-raw/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'closed pull requests',
-    value: Joi.string().regex(/^\w+?$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'closed pull requests',
+      value: Joi.string().regex(/^\w+?$/),
+    })
+  )
 
 t.create('GitHub pull requests')
   .get('/issues-pr/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'pull requests',
-    value: isMetricOpenIssues
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'pull requests',
+      value: isMetricOpenIssues,
+    })
+  )
 
 t.create('GitHub pull requests raw')
   .get('/issues-pr-raw/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'open pull requests',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'open pull requests',
+      value: isMetric,
+    })
+  )
 
 t.create('GitHub closed issues')
   .get('/issues-closed/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'issues',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? closed$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'issues',
+      value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? closed$/),
+    })
+  )
 
 t.create('GitHub closed issues raw')
   .get('/issues-closed-raw/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'closed issues',
-    value: Joi.string().regex(/^\w+\+?$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'closed issues',
+      value: Joi.string().regex(/^\w+\+?$/),
+    })
+  )
 
 t.create('GitHub open issues')
   .get('/issues/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'issues',
-    value: isMetricOpenIssues
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'issues',
+      value: isMetricOpenIssues,
+    })
+  )
 
 t.create('GitHub open issues raw')
   .get('/issues-raw/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'open issues', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'open issues', value: isMetric }))
 
 t.create('GitHub open issues by label is > zero')
   .get('/issues/badges/shields/service-badge.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'service-badge issues',
-    value: isMetricOpenIssues
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'service-badge issues',
+      value: isMetricOpenIssues,
+    })
+  )
 
 t.create('GitHub open issues by multi-word label is > zero')
   .get('/issues/Cockatrice/Cockatrice/App%20-%20Cockatrice.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: '"App - Cockatrice" issues',
-    value: isMetricOpenIssues
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: '"App - Cockatrice" issues',
+      value: isMetricOpenIssues,
+    })
+  )
 
 t.create('GitHub open issues by label (raw)')
   .get('/issues-raw/badges/shields/service-badge.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'open service-badge issues',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'open service-badge issues',
+      value: isMetric,
+    })
+  )
 
 t.create('GitHub open issues (repo not found)')
   .get('/issues-raw/badges/helmets.json')
   .expectJSON({
     name: 'open issues',
-    value: 'repo not found'
-  });
+    value: 'repo not found',
+  })
 
 t.create('GitHub open pull requests by label')
   .get('/issues-pr/badges/shields/service-badge.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'service-badge pull requests',
-    value: isMetricOpenIssues
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'service-badge pull requests',
+      value: isMetricOpenIssues,
+    })
+  )
 
 t.create('GitHub open pull requests by label (raw)')
   .get('/issues-pr-raw/badges/shields/service-badge.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'open service-badge pull requests',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'open service-badge pull requests',
+      value: isMetric,
+    })
+  )
 
 t.create('Followers')
   .get('/followers/webcaetano.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'followers',
-    value: Joi.string().regex(/^\w+$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'followers',
+      value: Joi.string().regex(/^\w+$/),
+    })
+  )
 
 t.create('Followers (user not found)')
   .get('/followers/PyvesB2.json')
   .expectJSON({
     name: 'followers',
-    value: 'user not found'
-  });
+    value: 'user not found',
+  })
 
 t.create('Watchers')
   .get('/watchers/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'watchers',
-    value: Joi.number().integer().positive()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'watchers',
+      value: Joi.number()
+        .integer()
+        .positive(),
+    })
+  )
 
 t.create('Watchers (repo not found)')
   .get('/watchers/badges/helmets.json')
   .expectJSON({
     name: 'watchers',
-    value: 'repo not found'
-  });
+    value: 'repo not found',
+  })
 
 t.create('Stars')
   .get('/stars/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'stars',
-    value: Joi.string().regex(/^\w+$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'stars',
+      value: Joi.string().regex(/^\w+$/),
+    })
+  )
 
 t.create('Stars (repo not found)')
   .get('/stars/badges/helmets.json')
   .expectJSON({
     name: 'stars',
-    value: 'repo not found'
-  });
+    value: 'repo not found',
+  })
 
 t.create('Forks')
   .get('/forks/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'forks',
-    value: Joi.number().integer().positive()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'forks',
+      value: Joi.number()
+        .integer()
+        .positive(),
+    })
+  )
 
 t.create('Forks (repo not found)')
   .get('/forks/badges/helmets.json')
   .expectJSON({
     name: 'forks',
-    value: 'repo not found'
-  });
+    value: 'repo not found',
+  })
 
 t.create('Commits since')
-  .get('/commits-since/badges/shields/a0663d8da53fb712472c02665e6ff7547ba945b7.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: Joi.string().regex(/^(commits since){1}[\s\S]+$/),
-    value: Joi.string().regex(/^\w+$/)
-  }));
+  .get(
+    '/commits-since/badges/shields/a0663d8da53fb712472c02665e6ff7547ba945b7.json'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: Joi.string().regex(/^(commits since){1}[\s\S]+$/),
+      value: Joi.string().regex(/^\w+$/),
+    })
+  )
 
 t.create('Commits since by latest release')
   .get('/commits-since/microsoft/typescript/latest.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: Joi.string().regex(/^(commits since){1}[\s\S]+$/),
-    value: Joi.string().regex(/^\d+\w?$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: Joi.string().regex(/^(commits since){1}[\s\S]+$/),
+      value: Joi.string().regex(/^\d+\w?$/),
+    })
+  )
 
 t.create('Release')
   .get('/release/photonstorm/phaser.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'release', value: Joi.string() }));
+  .expectJSONTypes(Joi.object().keys({ name: 'release', value: Joi.string() }))
 
 t.create('Release (repo not found)')
   .get('/release/badges/helmets.json')
-  .expectJSON({ name: 'release', value: 'repo not found' });
+  .expectJSON({ name: 'release', value: 'repo not found' })
 
 t.create('(pre-)Release')
   .get('/release/photonstorm/phaser/all.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'release', value: Joi.string() }));
+  .expectJSONTypes(Joi.object().keys({ name: 'release', value: Joi.string() }))
 
 t.create('Release Date. e.g release date|today')
-.get('/release-date/microsoft/vscode.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'release date',
-  value: isFormattedDate
-}));
+  .get('/release-date/microsoft/vscode.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'release date',
+      value: isFormattedDate,
+    })
+  )
 
 t.create('Release Date - Custom Label. e.g myRelease|today')
-.get('/release-date/microsoft/vscode.json?label=myRelease')
-.expectJSONTypes(Joi.object().keys({
-  name: 'myRelease',
-  value: isFormattedDate
-}));
-
-t.create('Release Date - Should return `no releases or repo not found` for invalid repo')
-.get('/release-date/not-valid-name/not-valid-repo.json')
-.expectJSON({ name: 'release date', value: 'no releases or repo not found' });
+  .get('/release-date/microsoft/vscode.json?label=myRelease')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'myRelease',
+      value: isFormattedDate,
+    })
+  )
+
+t.create(
+  'Release Date - Should return `no releases or repo not found` for invalid repo'
+)
+  .get('/release-date/not-valid-name/not-valid-repo.json')
+  .expectJSON({ name: 'release date', value: 'no releases or repo not found' })
 
 t.create('(Pre-)Release Date. e.g release date|today')
-.get('/release-date-pre/microsoft/vscode.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'release date',
-  value: isFormattedDate
-}));
+  .get('/release-date-pre/microsoft/vscode.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'release date',
+      value: isFormattedDate,
+    })
+  )
 
 t.create('(Pre-)Release Date - Custom Label. e.g myRelease|today')
-.get('/release-date-pre/microsoft/vscode.json?label=myRelease')
-.expectJSONTypes(Joi.object().keys({
-  name: 'myRelease',
-  value: isFormattedDate
-}));
-
-t.create('(Pre-)Release Date - Should return `no releases or repo not found` for invalid repo')
-.get('/release-date-pre/not-valid-name/not-valid-repo.json')
-.expectJSON({ name: 'release date', value: 'no releases or repo not found' });
-
+  .get('/release-date-pre/microsoft/vscode.json?label=myRelease')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'myRelease',
+      value: isFormattedDate,
+    })
+  )
+
+t.create(
+  '(Pre-)Release Date - Should return `no releases or repo not found` for invalid repo'
+)
+  .get('/release-date-pre/not-valid-name/not-valid-repo.json')
+  .expectJSON({ name: 'release date', value: 'no releases or repo not found' })
 
 t.create('Tag')
   .get('/tag/photonstorm/phaser.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'tag', value: Joi.string() }));
+  .expectJSONTypes(Joi.object().keys({ name: 'tag', value: Joi.string() }))
 
 t.create('Tag (repo not found)')
   .get('/tag/badges/helmets.json')
-  .expectJSON({ name: 'tag', value: 'repo not found' });
+  .expectJSON({ name: 'tag', value: 'repo not found' })
 
 t.create('Package version')
   .get('/package-json/v/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'package',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'package',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('Package version (repo not found)')
   .get('/package-json/v/badges/helmets.json')
   .expectJSON({
     name: 'package',
-    value: 'repo not found'
-  });
+    value: 'repo not found',
+  })
 
 t.create('Package name')
   .get('/package-json/n/badges/shields.json')
-  .expectJSON({ name: 'package name', value: 'gh-badges' });
+  .expectJSON({ name: 'package name', value: 'gh-badges' })
 
 t.create('Package name - Custom label')
   .get('/package-json/name/badges/shields.json?label=Dev Name')
-  .expectJSON({ name: 'Dev Name', value: 'gh-badges' });
+  .expectJSON({ name: 'Dev Name', value: 'gh-badges' })
 
 t.create('Package array')
   .get('/package-json/keywords/badges/shields.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'package keywords',
-    value: Joi.string().regex(/.*?,/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'package keywords',
+      value: Joi.string().regex(/.*?,/),
+    })
+  )
 
 t.create('Package object')
   .get('/package-json/dependencies/badges/shields.json')
-  .expectJSON({ name: 'package dependencies', value: 'invalid data' });
+  .expectJSON({ name: 'package dependencies', value: 'invalid data' })
 
 t.create('Manifest version')
   .get('/manifest-json/v/RedSparr0w/IndieGala-Helper.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'manifest',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'manifest',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('Manifest name')
   .get('/manifest-json/n/RedSparr0w/IndieGala-Helper.json')
-  .expectJSON({ name: 'manifest name', value: 'IndieGala Helper' });
+  .expectJSON({ name: 'manifest name', value: 'IndieGala Helper' })
 
 t.create('Manifest array')
   .get('/manifest-json/permissions/RedSparr0w/IndieGala-Helper.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'manifest permissions',
-    value: Joi.string().regex(/.*?,/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'manifest permissions',
+      value: Joi.string().regex(/.*?,/),
+    })
+  )
 
 t.create('Manifest object')
   .get('/manifest-json/background/RedSparr0w/IndieGala-Helper.json')
-  .expectJSON({ name: 'manifest background', value: 'invalid data' });
+  .expectJSON({ name: 'manifest background', value: 'invalid data' })
 
 t.create('Manifest invalid json response')
   .get('/manifest-json/v/RedSparr0w/not-a-real-project.json')
-  .expectJSON({ name: 'manifest', value: 'repo not found' });
+  .expectJSON({ name: 'manifest', value: 'repo not found' })
 
 t.create('Manifest no network connection')
   .get('/manifest-json/v/RedSparr0w/IndieGala-Helper.json')
   .networkOff()
-  .expectJSON({ name: 'manifest', value: 'inaccessible' });
+  .expectJSON({ name: 'manifest', value: 'inaccessible' })
 
 t.create('File size')
   .get('/size/webcaetano/craft/build/phaser-craft.min.js.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'size', value: isFileSize }));
+  .expectJSONTypes(Joi.object().keys({ name: 'size', value: isFileSize }))
 
 t.create('File size 404')
   .get('/size/webcaetano/craft/build/does-not-exist.min.js.json')
-  .expectJSON({ name: 'size', value: 'repo or file not found' });
+  .expectJSON({ name: 'size', value: 'repo or file not found' })
 
 t.create('File size for "not a regular file"')
   .get('/size/webcaetano/craft/build.json')
-  .expectJSON({ name: 'size', value: 'not a regular file' });
+  .expectJSON({ name: 'size', value: 'not a regular file' })
 
 t.create('Downloads all releases')
   .get('/downloads/photonstorm/phaser/total.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: Joi.string().regex(/^\w+\s+total$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: Joi.string().regex(/^\w+\s+total$/),
+    })
+  )
 
 t.create('Downloads all releases (repo not found)')
   .get('/downloads/badges/helmets/total.json')
   .expectJSON({
     name: 'downloads',
-    value: 'repo or release not found'
-  });
+    value: 'repo or release not found',
+  })
 
 t.create('downloads for latest release')
   .get('/downloads/photonstorm/phaser/latest/total.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }))
 
 t.create('downloads-pre for latest release')
   .get('/downloads-pre/photonstorm/phaser/latest/total.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }))
 
 t.create('downloads for release without slash')
   .get('/downloads/atom/atom/v0.190.0/total.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? v0\.190\.0$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? v0\.190\.0$/),
+    })
+  )
 
 t.create('downloads for specific asset without slash')
   .get('/downloads/atom/atom/v0.190.0/atom-amd64.deb.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? v0\.190\.0 \[atom-amd64\.deb\]$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: Joi.string().regex(
+        /^[0-9]+[kMGTPEZY]? v0\.190\.0 \[atom-amd64\.deb\]$/
+      ),
+    })
+  )
 
 t.create('downloads for specific asset from latest release')
   .get('/downloads/atom/atom/latest/atom-amd64.deb.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? \[atom-amd64\.deb\]$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? \[atom-amd64\.deb\]$/),
+    })
+  )
 
 t.create('downloads-pre for specific asset from latest release')
   .get('/downloads-pre/atom/atom/latest/atom-amd64.deb.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? \[atom-amd64\.deb\]$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? \[atom-amd64\.deb\]$/),
+    })
+  )
 
 t.create('downloads for release with slash')
   .get('/downloads/NHellFire/dban/stable/v2.2.8/total.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? stable\/v2\.2\.8$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? stable\/v2\.2\.8$/),
+    })
+  )
 
 t.create('downloads for specific asset with slash')
   .get('/downloads/NHellFire/dban/stable/v2.2.8/dban-2.2.8_i586.iso.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: Joi.string().regex(/^[0-9]+[kMGTPEZY]? stable\/v2\.2\.8 \[dban-2\.2\.8_i586\.iso\]$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: Joi.string().regex(
+        /^[0-9]+[kMGTPEZY]? stable\/v2\.2\.8 \[dban-2\.2\.8_i586\.iso\]$/
+      ),
+    })
+  )
 
 t.create('downloads for unknown release')
   .get('/downloads/atom/atom/does-not-exist/total.json')
-  .expectJSON({ name: 'downloads', value: 'repo or release not found' });
+  .expectJSON({ name: 'downloads', value: 'repo or release not found' })
 
 t.create('hit counter')
   .get('/search/torvalds/linux/goto.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'goto counter', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'goto counter', value: isMetric }))
 
 t.create('hit counter for nonexistent repo')
   .get('/search/torvalds/not-linux/goto.json')
-  .expectJSON({ name: 'goto counter', value: 'repo not found' });
+  .expectJSON({ name: 'goto counter', value: 'repo not found' })
 
 t.create('commit activity (1 year)')
   .get('/commit-activity/y/eslint/eslint.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'commit activity',
-    value: isMetricOverTimePeriod,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'commit activity',
+      value: isMetricOverTimePeriod,
+    })
+  )
 
 t.create('commit activity (4 weeks)')
   .get('/commit-activity/4w/eslint/eslint.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'commit activity',
-    value: isMetricOverTimePeriod,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'commit activity',
+      value: isMetricOverTimePeriod,
+    })
+  )
 
 t.create('commit activity (1 week)')
   .get('/commit-activity/w/eslint/eslint.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'commit activity',
-    value: isMetricOverTimePeriod,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'commit activity',
+      value: isMetricOverTimePeriod,
+    })
+  )
 
 t.create('commit activity (repo not found)')
   .get('/commit-activity/w/badges/helmets.json')
   .expectJSON({
     name: 'commit activity',
     value: 'repo not found',
-  });
+  })
 
 t.create('last commit (recent)')
   .get('/last-commit/eslint/eslint.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'last commit', value: isFormattedDate }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'last commit', value: isFormattedDate })
+  )
 
 t.create('last commit (ancient)')
   .get('/last-commit/badges/badgr.co.json')
-  .expectJSON({ name: 'last commit', value: 'january 2014' });
+  .expectJSON({ name: 'last commit', value: 'january 2014' })
 
 t.create('last commit (on branch)')
   .get('/last-commit/badges/badgr.co/shielded.json')
-  .expectJSON({ name: 'last commit', value: 'july 2013' });
+  .expectJSON({ name: 'last commit', value: 'july 2013' })
 
 t.create('last commit (repo not found)')
   .get('/last-commit/badges/helmets.json')
-  .expectJSON({ name: 'last commit', value: 'repo not found' });
+  .expectJSON({ name: 'last commit', value: 'repo not found' })
 
 t.create('github issue state')
   .get('/issues/detail/s/badges/shields/979.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'issue 979',
-    value: Joi.equal('open', 'closed'),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'issue 979',
+      value: Joi.equal('open', 'closed'),
+    })
+  )
 
 t.create('github issue state (repo not found)')
   .get('/issues/detail/s/badges/helmets/979.json')
   .expectJSON({
     name: 'issue/pull request 979',
     value: 'issue, pull request or repo not found',
-  });
+  })
 
 t.create('github issue title')
   .get('/issues/detail/title/badges/shields/979.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'issue 979',
-    value: 'Github rate limits cause transient service test failures in CI',
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'issue 979',
+      value: 'Github rate limits cause transient service test failures in CI',
+    })
+  )
 
 t.create('github issue author')
   .get('/issues/detail/u/badges/shields/979.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'author', value: 'paulmelnikow' }));
+  .expectJSONTypes(Joi.object().keys({ name: 'author', value: 'paulmelnikow' }))
 
 t.create('github issue label')
   .get('/issues/detail/label/badges/shields/979.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'label',
-    value: Joi.equal('bug | developer-experience', 'developer-experience | bug'),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'label',
+      value: Joi.equal(
+        'bug | developer-experience',
+        'developer-experience | bug'
+      ),
+    })
+  )
 
 t.create('github issue comments')
   .get('/issues/detail/comments/badges/shields/979.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'comments',
-    value: Joi.number().greater(15),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'comments',
+      value: Joi.number().greater(15),
+    })
+  )
 
 t.create('github issue age')
   .get('/issues/detail/age/badges/shields/979.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'created', value: isFormattedDate }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'created', value: isFormattedDate })
+  )
 
 t.create('github issue update')
   .get('/issues/detail/last-update/badges/shields/979.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'updated', value: isFormattedDate }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'updated', value: isFormattedDate })
+  )
 
 t.create('github pull request check state')
   .get('/status/s/pulls/badges/shields/1110.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'checks', value: 'failure' }));
+  .expectJSONTypes(Joi.object().keys({ name: 'checks', value: 'failure' }))
 
 t.create('github pull request check state (pull request not found)')
   .get('/status/s/pulls/badges/shields/5110.json')
-  .expectJSON({ name: 'checks', value: 'pull request or repo not found' });
+  .expectJSON({ name: 'checks', value: 'pull request or repo not found' })
 
 t.create('github pull request check contexts')
   .get('/status/contexts/pulls/badges/shields/1110.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'checks', value: '1 failure' }));
+  .expectJSONTypes(Joi.object().keys({ name: 'checks', value: '1 failure' }))
 
 t.create('top language')
-.get('/languages/top/badges/shields.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'JavaScript',
-  value: Joi.string().regex(/^([1-9]?[0-9]\.[0-9]|100\.0)%$/),
-}));
+  .get('/languages/top/badges/shields.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'JavaScript',
+      value: Joi.string().regex(/^([1-9]?[0-9]\.[0-9]|100\.0)%$/),
+    })
+  )
 
 t.create('top language with empty repository')
-.get('/languages/top/pyvesb/emptyrepo.json')
-.expectJSON({ name: 'language', value: 'none' });
+  .get('/languages/top/pyvesb/emptyrepo.json')
+  .expectJSON({ name: 'language', value: 'none' })
 
 t.create('language count')
-.get('/languages/count/badges/shields.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'languages',
-  value: Joi.number().integer().positive(),
-}));
+  .get('/languages/count/badges/shields.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'languages',
+      value: Joi.number()
+        .integer()
+        .positive(),
+    })
+  )
 
 t.create('language count (repo not found)')
   .get('/languages/count/badges/helmets.json')
   .expectJSON({
     name: 'languages',
     value: 'repo not found',
-  });
+  })
 
 t.create('code size in bytes for all languages')
-.get('/languages/code-size/badges/shields.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'code size',
-  value: isFileSize,
-}));
+  .get('/languages/code-size/badges/shields.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'code size',
+      value: isFileSize,
+    })
+  )
 
 t.create('repository size')
-.get('/repo-size/badges/shields.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'repo size',
-  value: isFileSize,
-}));
+  .get('/repo-size/badges/shields.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'repo size',
+      value: isFileSize,
+    })
+  )
 
 t.create('repository size (repo not found)')
   .get('/repo-size/badges/helmets.json')
   .expectJSON({
     name: 'repo size',
     value: 'repo not found',
-  });
+  })
 
 // Commit status
 t.create('commit status - commit in branch')
-.get('/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test')
-.expectJSON({
-  name: 'commit status',
-  value: 'in master',
-  colorB: colorsB.brightgreen
-});
-
-t.create('commit status - checked commit is identical with the newest commit in branch')
-  .get('/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test')
-  .intercept(nock => nock('https://api.github.com')
-    .get('/repos/badges/shields/compare/master...5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c')
-    .reply(200, { status: 'identical' }))
+  .get(
+    '/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test'
+  )
   .expectJSON({
     name: 'commit status',
     value: 'in master',
-    colorB: colorsB.brightgreen
-});
+    colorB: colorsB.brightgreen,
+  })
+
+t.create(
+  'commit status - checked commit is identical with the newest commit in branch'
+)
+  .get(
+    '/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test'
+  )
+  .intercept(nock =>
+    nock('https://api.github.com')
+      .get(
+        '/repos/badges/shields/compare/master...5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c'
+      )
+      .reply(200, { status: 'identical' })
+  )
+  .expectJSON({
+    name: 'commit status',
+    value: 'in master',
+    colorB: colorsB.brightgreen,
+  })
 
 t.create('commit status - commit not in branch')
-.get('/commit-status/badges/shields/master/960c5bf72d7d1539fcd453343eed3f8617427a41.json?style=_shields_test')
-.expectJSON({
-  name: 'commit status',
-  value: 'commit or branch not found',
-  colorB: colorsB.lightgrey
-});
+  .get(
+    '/commit-status/badges/shields/master/960c5bf72d7d1539fcd453343eed3f8617427a41.json?style=_shields_test'
+  )
+  .expectJSON({
+    name: 'commit status',
+    value: 'commit or branch not found',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('commit status - unknown commit id')
-.get('/commit-status/atom/atom/v1.27.1/7dfb45eb61a48a4ce18a0dd2e31f944ed4467ae3.json?style=_shields_test')
-.expectJSON({
-  name: 'commit status',
-  value: 'not in v1.27.1',
-  colorB: colorsB.yellow
-});
+  .get(
+    '/commit-status/atom/atom/v1.27.1/7dfb45eb61a48a4ce18a0dd2e31f944ed4467ae3.json?style=_shields_test'
+  )
+  .expectJSON({
+    name: 'commit status',
+    value: 'not in v1.27.1',
+    colorB: colorsB.yellow,
+  })
 
 t.create('commit status - unknown branch')
-.get('/commit-status/badges/shields/this-branch-does-not-exist/b551a3a8daf1c48dba32a3eab1edf99b10c28863.json?style=_shields_test')
-.expectJSON({
-  name: 'commit status',
-  value: 'commit or branch not found',
-  colorB: colorsB.lightgrey
-});
+  .get(
+    '/commit-status/badges/shields/this-branch-does-not-exist/b551a3a8daf1c48dba32a3eab1edf99b10c28863.json?style=_shields_test'
+  )
+  .expectJSON({
+    name: 'commit status',
+    value: 'commit or branch not found',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('commit status - no common ancestor between commit and branch')
-.get('/commit-status/badges/shields/master/b551a3a8daf1c48dba32a3eab1edf99b10c28863.json?style=_shields_test')
-.expectJSON({
-  name: 'commit status',
-  value: 'no common ancestor',
-  colorB: colorsB.lightgrey
-});
+  .get(
+    '/commit-status/badges/shields/master/b551a3a8daf1c48dba32a3eab1edf99b10c28863.json?style=_shields_test'
+  )
+  .expectJSON({
+    name: 'commit status',
+    value: 'no common ancestor',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('commit status - invalid JSON')
-  .get('/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test')
-  .intercept(nock => nock('https://api.github.com')
-    .get('/repos/badges/shields/compare/master...5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c')
-    .reply(invalidJSON))
+  .get(
+    '/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test'
+  )
+  .intercept(nock =>
+    nock('https://api.github.com')
+      .get(
+        '/repos/badges/shields/compare/master...5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c'
+      )
+      .reply(invalidJSON)
+  )
   .expectJSON({
     name: 'commit status',
     value: 'invalid',
-    colorB: colorsB.lightgrey
-});
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('commit status - network error')
-  .get('/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test')
+  .get(
+    '/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test'
+  )
   .networkOff()
   .expectJSON({
     name: 'commit status',
     value: 'inaccessible',
-    colorB: colorsB.red
-});
+    colorB: colorsB.red,
+  })
 
 t.create('commit status - github server error')
-  .get('/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test')
-  .intercept(nock => nock('https://api.github.com')
-    .get('/repos/badges/shields/compare/master...5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c')
-    .reply(500))
+  .get(
+    '/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test'
+  )
+  .intercept(nock =>
+    nock('https://api.github.com')
+      .get(
+        '/repos/badges/shields/compare/master...5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c'
+      )
+      .reply(500)
+  )
   .expectJSON({
     name: 'commit status',
     value: 'invalid',
-    colorB: colorsB.lightgrey
-});
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('commit status - 404 with empty JSON form github')
-  .get('/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test')
-  .intercept(nock => nock('https://api.github.com')
-    .get('/repos/badges/shields/compare/master...5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c')
-    .reply(404, {}))
+  .get(
+    '/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test'
+  )
+  .intercept(nock =>
+    nock('https://api.github.com')
+      .get(
+        '/repos/badges/shields/compare/master...5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c'
+      )
+      .reply(404, {})
+  )
   .expectJSON({
     name: 'commit status',
     value: 'invalid',
-    colorB: colorsB.lightgrey
-});
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('commit status - 404 with invalid JSON form github')
-  .get('/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test')
-  .intercept(nock => nock('https://api.github.com')
-    .get('/repos/badges/shields/compare/master...5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c')
-    .reply(404, invalidJSON))
+  .get(
+    '/commit-status/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json?style=_shields_test'
+  )
+  .intercept(nock =>
+    nock('https://api.github.com')
+      .get(
+        '/repos/badges/shields/compare/master...5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c'
+      )
+      .reply(404, invalidJSON)
+  )
   .expectJSON({
     name: 'commit status',
     value: 'invalid',
-    colorB: colorsB.lightgrey
-});
+    colorB: colorsB.lightgrey,
+  })
diff --git a/services/gratipay/gratipay.tester.js b/services/gratipay/gratipay.tester.js
index 14f4e64aac75026a8be3d56a0c6c7cc4c7ba1cdc..feb28c7d76148960f6f680738b810febfa968e63 100644
--- a/services/gratipay/gratipay.tester.js
+++ b/services/gratipay/gratipay.tester.js
@@ -1,13 +1,13 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'gratipay', title: 'Gratipay' });
-module.exports = t;
+const t = new ServiceTester({ id: 'gratipay', title: 'Gratipay' })
+module.exports = t
 
 t.create('Receiving')
   .get('/Gratipay.json')
   .expectJSON({
     name: 'gratipay',
     value: 'no longer available',
-  });
+  })
diff --git a/services/hackage/hackage.tester.js b/services/hackage/hackage.tester.js
index a9c4d7e143ad8cf494030c4954dd5c16b3285d1f..9f18b2d17354b65d9a7b5f28912d62b16f4db269 100644
--- a/services/hackage/hackage.tester.js
+++ b/services/hackage/hackage.tester.js
@@ -1,50 +1,54 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators');
-
-const t = new ServiceTester({ id: 'hackage', title: 'Hackage' });
-module.exports = t;
+const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
 
+const t = new ServiceTester({ id: 'hackage', title: 'Hackage' })
+module.exports = t
 
 t.create('hackage version (valid)')
   .get('/v/lens.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'hackage',
-    value: isVPlusDottedVersionAtLeastOne,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'hackage',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('hackage deps (valid)')
   .get('-deps/v/lens.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'dependencies',
-    value: Joi.string().regex(/^(up to date|outdated)$/),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'dependencies',
+      value: Joi.string().regex(/^(up to date|outdated)$/),
+    })
+  )
 
 t.create('hackage version (not found)')
   .get('/v/not-a-package.json')
-  .expectJSON({name: 'hackage', value: 'not found'});
+  .expectJSON({ name: 'hackage', value: 'not found' })
 
 t.create('hackage version (not found)')
   .get('-deps/v/not-a-package.json')
-  .expectJSON({name: 'dependencies', value: 'not found'});
+  .expectJSON({ name: 'dependencies', value: 'not found' })
 
 t.create('hackage version (connection error)')
   .get('/v/lens.json')
   .networkOff()
-  .expectJSON({name: 'hackage', value: 'inaccessible'});
+  .expectJSON({ name: 'hackage', value: 'inaccessible' })
 
 t.create('hackage deps (connection error)')
   .get('-deps/v/lens.json')
   .networkOff()
-  .expectJSON({name: 'dependencies', value: 'inaccessible'});
+  .expectJSON({ name: 'dependencies', value: 'inaccessible' })
 
 t.create('hackage version (unexpected response)')
   .get('/v/lens.json')
-  .intercept(nock => nock('https://hackage.haskell.org')
-    .get('/package/lens/lens.cabal')
-    .reply(200, "")
+  .intercept(nock =>
+    nock('https://hackage.haskell.org')
+      .get('/package/lens/lens.cabal')
+      .reply(200, '')
   )
-  .expectJSON({name: 'hackage', value: 'invalid'});
+  .expectJSON({ name: 'hackage', value: 'invalid' })
diff --git a/services/hexpm/hexpm.tester.js b/services/hexpm/hexpm.tester.js
index 3878195edaa18bff4c90a9de6f2bdbab34b4e93d..68546e3c9d29e0bbd76a2da1cca722053fa4a6f7 100644
--- a/services/hexpm/hexpm.tester.js
+++ b/services/hexpm/hexpm.tester.js
@@ -1,45 +1,48 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const {
-  isMetric,
-  isMetricOverTimePeriod
-} = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isMetric, isMetricOverTimePeriod } = require('../test-validators')
 
-const isHexpmVersion = Joi.string().regex(/^v\d+.\d+.?\d?$/);
+const isHexpmVersion = Joi.string().regex(/^v\d+.\d+.?\d?$/)
 
-const t = new ServiceTester({ id: 'hexpm', title: 'Hex.pm' });
-module.exports = t;
+const t = new ServiceTester({ id: 'hexpm', title: 'Hex.pm' })
+module.exports = t
 
 t.create('downloads per week')
   .get('/dw/cowboy.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetricOverTimePeriod }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'downloads', value: isMetricOverTimePeriod })
+  )
 
 t.create('downloads per day')
   .get('/dd/cowboy.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetricOverTimePeriod }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'downloads', value: isMetricOverTimePeriod })
+  )
 
 t.create('downloads in total')
   .get('/dt/cowboy.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }))
 
 t.create('version')
   .get('/v/cowboy.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'hex', value: isHexpmVersion }));
+  .expectJSONTypes(Joi.object().keys({ name: 'hex', value: isHexpmVersion }))
 
 t.create('license')
   .get('/l/cowboy.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'license',
-    value: Joi.string().required()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'license',
+      value: Joi.string().required(),
+    })
+  )
 
 t.create('unknown repo')
   .get('/l/this-repo-does-not-exist.json')
-  .expectJSON({ name: 'hex', value: 'invalid' });
+  .expectJSON({ name: 'hex', value: 'invalid' })
 
 t.create('connection error')
   .get('/l/cowboy.json')
   .networkOff()
-  .expectJSON({ name: 'hex', value: 'inaccessible' });
+  .expectJSON({ name: 'hex', value: 'inaccessible' })
diff --git a/services/hhvm/hhvm.tester.js b/services/hhvm/hhvm.tester.js
index 9988e50f8096b9e91639fc30725bbe9d1d793359..c94d38e366dd699b2ed87c7b48eddb951694fa55 100644
--- a/services/hhvm/hhvm.tester.js
+++ b/services/hhvm/hhvm.tester.js
@@ -1,46 +1,53 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
 
-const t = new ServiceTester({ id: 'hhvm', title: 'hhvm status' });
+const t = new ServiceTester({ id: 'hhvm', title: 'hhvm status' })
 
-const isAllowedStatus = Joi.string().regex(/^(tested|partially tested|not tested|maybe untested)$/);
+const isAllowedStatus = Joi.string().regex(
+  /^(tested|partially tested|not tested|maybe untested)$/
+)
 
-module.exports = t;
+module.exports = t
 
 t.create('get default branch')
-    .get('/symfony/symfony.json')
-    .expectJSONTypes(Joi.object().keys({
+  .get('/symfony/symfony.json')
+  .expectJSONTypes(
+    Joi.object().keys({
       name: 'hhvm',
-      value: isAllowedStatus
-    }));
+      value: isAllowedStatus,
+    })
+  )
 
 t.create('get specific branch')
-    .get('/yiisoft/yii/1.1.19.json')
-    .expectJSONTypes(Joi.object().keys({
+  .get('/yiisoft/yii/1.1.19.json')
+  .expectJSONTypes(
+    Joi.object().keys({
       name: 'hhvm',
-      value: isAllowedStatus
-    }));
+      value: isAllowedStatus,
+    })
+  )
 
 t.create('invalid repo')
-    .get('/frodo/is-not-a-package.json')
-    .expectJSON({ name: 'hhvm', value: 'repo not found' });
+  .get('/frodo/is-not-a-package.json')
+  .expectJSON({ name: 'hhvm', value: 'repo not found' })
 
 t.create('invalid branch')
-    .get('/yiisoft/yii/1.1.666.json')
-    .expectJSON({ name: 'hhvm', value: 'branch not found' });
+  .get('/yiisoft/yii/1.1.666.json')
+  .expectJSON({ name: 'hhvm', value: 'branch not found' })
 
 t.create('connection error')
   .get('/symfony/symfony.json')
   .networkOff()
-  .expectJSON({name: 'hhvm', value: 'inaccessible'});
+  .expectJSON({ name: 'hhvm', value: 'inaccessible' })
 
 t.create('unexpected response')
-   .get('/symfony/symfony.json')
-   .intercept(nock => nock('https://php-eye.com')
-     .get('/api/v1/package/symfony/symfony.json')
-     .reply(invalidJSON)
-   )
-   .expectJSON({name: 'hhvm', value: 'invalid'});
+  .get('/symfony/symfony.json')
+  .intercept(nock =>
+    nock('https://php-eye.com')
+      .get('/api/v1/package/symfony/symfony.json')
+      .reply(invalidJSON)
+  )
+  .expectJSON({ name: 'hhvm', value: 'invalid' })
diff --git a/services/homebrew/homebrew.tester.js b/services/homebrew/homebrew.tester.js
index 3962ed131d48bd2736fc627b46efeb4363618d0f..fb3c3ab0844451a0efb43be296359ee51d7c9e26 100644
--- a/services/homebrew/homebrew.tester.js
+++ b/services/homebrew/homebrew.tester.js
@@ -1,42 +1,45 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isVPlusTripleDottedVersion } = require('../test-validators');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'homebrew', title: 'homebrew' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isVPlusTripleDottedVersion } = require('../test-validators')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'homebrew', title: 'homebrew' })
+module.exports = t
 
 t.create('homebrew (valid)')
   .get('/v/cake.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'homebrew',
-    value: isVPlusTripleDottedVersion,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'homebrew',
+      value: isVPlusTripleDottedVersion,
+    })
+  )
 
 t.create('homebrew (valid, mocked response)')
   .get('/v/cake.json')
-  .intercept(nock => nock('https://formulae.brew.sh')
-    .get('/api/formula/cake.json')
-    .reply(200, {versions: {stable: '0.23.0', devel: null, head: null}})
+  .intercept(nock =>
+    nock('https://formulae.brew.sh')
+      .get('/api/formula/cake.json')
+      .reply(200, { versions: { stable: '0.23.0', devel: null, head: null } })
   )
-  .expectJSON({name: 'homebrew', value: 'v0.23.0'});
+  .expectJSON({ name: 'homebrew', value: 'v0.23.0' })
 
 t.create('homebrew (invalid)')
   .get('/v/not-a-package.json')
-  .expectJSON({name: 'homebrew', value: 'not found'});
+  .expectJSON({ name: 'homebrew', value: 'not found' })
 
 t.create('homebrew (connection error)')
   .get('/v/cake.json')
   .networkOff()
-  .expectJSON({name: 'homebrew', value: 'inaccessible'});
+  .expectJSON({ name: 'homebrew', value: 'inaccessible' })
 
 t.create('homebrew (unexpected response)')
   .get('/v/cake.json')
-  .intercept(nock => nock('https://formulae.brew.sh')
-    .get('/api/formula/cake.json')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://formulae.brew.sh')
+      .get('/api/formula/cake.json')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'homebrew', value: 'invalid'});
+  .expectJSON({ name: 'homebrew', value: 'invalid' })
diff --git a/services/index.js b/services/index.js
index 70f7b38dbf1e92c7ca6740a868c07c5293909757..7eaa68b237726ba3d52e1a88f6a9564ef006c31a 100644
--- a/services/index.js
+++ b/services/index.js
@@ -1,32 +1,32 @@
-'use strict';
+'use strict'
 
-const glob = require('glob');
+const glob = require('glob')
 
 function loadServiceClasses() {
   // New-style services
-  const services = glob.sync(`${__dirname}/**/*.service.js`)
-    .map(path => require(path));
+  const services = glob
+    .sync(`${__dirname}/**/*.service.js`)
+    .map(path => require(path))
 
-  const serviceClasses = [];
+  const serviceClasses = []
   services.forEach(service => {
     if (typeof service === 'function') {
-      serviceClasses.push(service);
+      serviceClasses.push(service)
     } else {
       for (const serviceClass in service) {
-        serviceClasses.push(service[serviceClass]);
+        serviceClasses.push(service[serviceClass])
       }
     }
-  });
+  })
 
-  return serviceClasses;
+  return serviceClasses
 }
 
 function loadTesters() {
-  return glob.sync(`${__dirname}/**/*.tester.js`)
-    .map(path => require(path));
+  return glob.sync(`${__dirname}/**/*.tester.js`).map(path => require(path))
 }
 
 module.exports = {
   loadServiceClasses,
   loadTesters,
-};
+}
diff --git a/services/itunes/itunes.tester.js b/services/itunes/itunes.tester.js
index 0062b24af624bb5035b1f4f004b3738fc77c8ace..e35a07f9a7eb65a1d41de513bf740b86af19a2a3 100644
--- a/services/itunes/itunes.tester.js
+++ b/services/itunes/itunes.tester.js
@@ -1,40 +1,41 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'itunes', title: 'iTunes' });
-module.exports = t;
+const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'itunes', title: 'iTunes' })
+module.exports = t
 
 t.create('iTunes version (valid)')
   .get('/v/324684580.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'itunes app store',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'itunes app store',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('iTunes version (not found)')
   .get('/v/9.json')
-  .expectJSON({name: 'itunes app store', value: 'not found'});
+  .expectJSON({ name: 'itunes app store', value: 'not found' })
 
 t.create('iTunes version (invalid)')
   .get('/v/x.json')
-  .expectJSON({name: 'itunes app store', value: 'invalid'});
+  .expectJSON({ name: 'itunes app store', value: 'invalid' })
 
 t.create('iTunes version (connection error)')
   .get('/v/324684580.json')
   .networkOff()
-  .expectJSON({name: 'itunes app store', value: 'inaccessible'});
+  .expectJSON({ name: 'itunes app store', value: 'inaccessible' })
 
 t.create('iTunes version (unexpected response)')
   .get('/v/324684580.json')
-  .intercept(nock => nock('https://itunes.apple.com')
-    .get('/lookup?id=324684580')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://itunes.apple.com')
+      .get('/lookup?id=324684580')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'itunes app store', value: 'invalid'});
-
+  .expectJSON({ name: 'itunes app store', value: 'invalid' })
diff --git a/services/jenkins/jenkins.tester.js b/services/jenkins/jenkins.tester.js
index 0b4f4a2ae7a8a083f698de1ad6d507af891e8a41..b9d88b99eb1cb5069ea80eb0c5d12358ea4ef7b9 100644
--- a/services/jenkins/jenkins.tester.js
+++ b/services/jenkins/jenkins.tester.js
@@ -1,79 +1,130 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'jenkins', title: 'Jenkins' });
-module.exports = t;
+const t = new ServiceTester({ id: 'jenkins', title: 'Jenkins' })
+module.exports = t
 
 t.create('cobertura: latest version')
   .get('/plugin/v/blueocean.json')
-  .intercept(nock => nock('https://updates.jenkins-ci.org')
-    .get('/current/update-center.actual.json')
-    .reply(200, { plugins: { blueocean: { version: '1.1.6' } } })
+  .intercept(nock =>
+    nock('https://updates.jenkins-ci.org')
+      .get('/current/update-center.actual.json')
+      .reply(200, { plugins: { blueocean: { version: '1.1.6' } } })
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'plugin',
+      value: Joi.string().regex(/^v(.*)$/),
+    })
   )
-  .expectJSONTypes(Joi.object().keys({
-    name: 'plugin',
-    value: Joi.string().regex(/^v(.*)$/)
-  }));
 
 t.create('cobertura: version 0')
   .get('/plugin/v/blueocean.json')
-  .intercept(nock => nock('https://updates.jenkins-ci.org')
-    .get('/current/update-center.actual.json')
-    .reply(200, { plugins: { blueocean: { version: '0' } } })
+  .intercept(nock =>
+    nock('https://updates.jenkins-ci.org')
+      .get('/current/update-center.actual.json')
+      .reply(200, { plugins: { blueocean: { version: '0' } } })
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'plugin',
+      value: Joi.string().regex(/^v0$/),
+    })
   )
-  .expectJSONTypes(Joi.object().keys({
-    name: 'plugin',
-    value: Joi.string().regex(/^v0$/)
-  }));
 
 t.create('cobertura: inexistent artifact')
   .get('/plugin/v/inexistent-artifact-id.json')
-  .intercept(nock => nock('https://updates.jenkins-ci.org')
-    .get('/current/update-center.actual.json')
-    .reply(200, { plugins: { blueocean: { version: '1.1.6' } } })
+  .intercept(nock =>
+    nock('https://updates.jenkins-ci.org')
+      .get('/current/update-center.actual.json')
+      .reply(200, { plugins: { blueocean: { version: '1.1.6' } } })
   )
-  .expectJSON({ name: 'plugin', value: 'not found' });
+  .expectJSON({ name: 'plugin', value: 'not found' })
 
 t.create('cobertura: connection error')
   .get('/plugin/v/blueocean.json')
   .networkOff()
-  .expectJSON({ name: 'plugin', value: 'inaccessible' });
+  .expectJSON({ name: 'plugin', value: 'inaccessible' })
 
 t.create('jacoco: 81% | valid coverage')
   .get('/j/https/updates.jenkins-ci.org/job/hello-project/job/master.json')
-  .intercept(nock => nock('https://updates.jenkins-ci.org')
-    .get('/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]')
-    .reply(200, { instructionCoverage: { covered: 39498, missed: 9508, percentage: 81, percentageFloat: 80.5983, total: 49006 } })
+  .intercept(nock =>
+    nock('https://updates.jenkins-ci.org')
+      .get(
+        '/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]'
+      )
+      .reply(200, {
+        instructionCoverage: {
+          covered: 39498,
+          missed: 9508,
+          percentage: 81,
+          percentageFloat: 80.5983,
+          total: 49006,
+        },
+      })
   )
-  .expectJSONTypes({ name: 'coverage', value: '81%' });
+  .expectJSONTypes({ name: 'coverage', value: '81%' })
 
 t.create('jacoco: inaccessible | request error')
   .get('/j/https/updates.jenkins-ci.org/job/hello-project/job/master.json')
   .networkOff()
-  .expectJSONTypes({ name: 'coverage', value: 'inaccessible' });
+  .expectJSONTypes({ name: 'coverage', value: 'inaccessible' })
 
 t.create('jacoco: inaccessible | invalid coverage object')
   .get('/j/https/updates.jenkins-ci.org/job/hello-project/job/master.json')
-  .intercept(nock => nock('https://updates.jenkins-ci.org')
-    .get('/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]')
-    .reply(200, { invalidCoverageObject: { covered: 39498, missed: 9508, percentage: 81, percentageFloat: 80.5983, total: 49006 } })
+  .intercept(nock =>
+    nock('https://updates.jenkins-ci.org')
+      .get(
+        '/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]'
+      )
+      .reply(200, {
+        invalidCoverageObject: {
+          covered: 39498,
+          missed: 9508,
+          percentage: 81,
+          percentageFloat: 80.5983,
+          total: 49006,
+        },
+      })
   )
-  .expectJSONTypes({ name: 'coverage', value: 'inaccessible' });
+  .expectJSONTypes({ name: 'coverage', value: 'inaccessible' })
 
 t.create('jacoco: unknown | invalid coverage (non-numeric)')
   .get('/j/https/updates.jenkins-ci.org/job/hello-project/job/master.json')
-  .intercept(nock => nock('https://updates.jenkins-ci.org')
-    .get('/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]')
-    .reply(200, { instructionCoverage: { covered: 39498, missed: 9508, percentage: 'non-numeric', percentageFloat: 80.5983, total: 49006 } })
+  .intercept(nock =>
+    nock('https://updates.jenkins-ci.org')
+      .get(
+        '/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]'
+      )
+      .reply(200, {
+        instructionCoverage: {
+          covered: 39498,
+          missed: 9508,
+          percentage: 'non-numeric',
+          percentageFloat: 80.5983,
+          total: 49006,
+        },
+      })
   )
-  .expectJSONTypes({ name: 'coverage', value: 'unknown' });
+  .expectJSONTypes({ name: 'coverage', value: 'unknown' })
 
 t.create('jacoco: unknown | exception handling')
   .get('/j/https/updates.jenkins-ci.org/job/hello-project/job/master.json')
-  .intercept(nock => nock('https://updates.jenkins-ci.org')
-    .get('/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]')
-    .reply(200, { instructionCoverage: { covered: 39498, missed: 9508, percentage: '81.x', percentageFloat: 80.5983, total: 49006 } })
+  .intercept(nock =>
+    nock('https://updates.jenkins-ci.org')
+      .get(
+        '/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]'
+      )
+      .reply(200, {
+        instructionCoverage: {
+          covered: 39498,
+          missed: 9508,
+          percentage: '81.x',
+          percentageFloat: 80.5983,
+          total: 49006,
+        },
+      })
   )
-  .expectJSONTypes({ name: 'coverage', value: 'unknown' });
+  .expectJSONTypes({ name: 'coverage', value: 'unknown' })
diff --git a/services/jetbrains/jetbrains.tester.js b/services/jetbrains/jetbrains.tester.js
index 6755220041c97bfbe1c739835f3976c3fe5d533b..8cb50f03a305d56aedb065c30cc44d555a5c9bae 100644
--- a/services/jetbrains/jetbrains.tester.js
+++ b/services/jetbrains/jetbrains.tester.js
@@ -1,77 +1,91 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isMetric, isSemver } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isMetric, isSemver } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'jetbrains', title: 'JetBrains' });
-module.exports = t;
+const t = new ServiceTester({ id: 'jetbrains', title: 'JetBrains' })
+module.exports = t
 
 t.create('downloads (number as a plugin id)')
   .get('/plugin/d/7495.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }))
 
 t.create('downloads (plugin id from plugin.xml)')
   .get('/plugin/d/org.intellij.scala.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }))
 
 t.create('downloads (user friendly plugin id)')
   .get('/plugin/d/1347-scala.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }))
 
 t.create('unknown plugin')
   .get('/plugin/d/unknown-plugin.json')
-  .expectJSON({ name: 'downloads', value: 'not found' });
+  .expectJSON({ name: 'downloads', value: 'not found' })
 
 t.create('connection error')
   .get('/plugin/d/7495.json')
   .networkOff()
-  .expectJSON({ name: 'downloads', value: 'inaccessible' });
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 t.create('server error')
   .get('/plugin/d/7495.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=7495')
-    .reply(500)
+  .intercept(nock =>
+    nock('https://plugins.jetbrains.com')
+      .get('/plugins/list?pluginId=7495')
+      .reply(500)
   )
-  .expectJSON({ name: 'downloads', value: 'inaccessible' });
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 t.create('empty response')
   .get('/plugin/d/7495.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=7495')
-    .reply(200, '')
+  .intercept(nock =>
+    nock('https://plugins.jetbrains.com')
+      .get('/plugins/list?pluginId=7495')
+      .reply(200, '')
   )
-  .expectJSON({ name: 'downloads', value: 'invalid' });
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('incorrect response format (JSON instead of XML)')
   .get('/plugin/d/7495.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=7495')
-    .reply(200, { downloads: 2 })
+  .intercept(nock =>
+    nock('https://plugins.jetbrains.com')
+      .get('/plugins/list?pluginId=7495')
+      .reply(200, { downloads: 2 })
   )
-  .expectJSON({ name: 'downloads', value: 'invalid' });
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('missing required XML element')
   .get('/plugin/d/9435.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=9435')
-    .reply(200, `<?xml version="1.0" encoding="UTF-8"?>
+  .intercept(
+    nock =>
+      nock('https://plugins.jetbrains.com')
+        .get('/plugins/list?pluginId=9435')
+        .reply(
+          200,
+          `<?xml version="1.0" encoding="UTF-8"?>
                  <plugin-repository>
                    <ff>"Code editing"</ff>
                    <category name="Code editing">
                      <!-- no required idea-plugin element here -->
                    </category>
-                 </plugin-repository>`), {
-                   'Content-Type': 'text/xml;charset=UTF-8'
-                 })
-  .expectJSON({ name: 'downloads', value: 'invalid' });
+                 </plugin-repository>`
+        ),
+    {
+      'Content-Type': 'text/xml;charset=UTF-8',
+    }
+  )
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('missing required XML attribute')
   .get('/plugin/d/9435.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=9435')
-    .reply(200, `<?xml version="1.0" encoding="UTF-8"?>
+  .intercept(
+    nock =>
+      nock('https://plugins.jetbrains.com')
+        .get('/plugins/list?pluginId=9435')
+        .reply(
+          200,
+          `<?xml version="1.0" encoding="UTF-8"?>
                  <plugin-repository>
                    <ff>"Code editing"</ff>
                    <category name="Code editing">
@@ -88,101 +102,130 @@ t.create('missing required XML attribute')
                        <rating>00</rating>
                      </idea-plugin>
                    </category>
-                 </plugin-repository>`), {
-                   'Content-Type': 'text/xml;charset=UTF-8'
-                 })
-  .expectJSON({ name: 'downloads', value: 'invalid' });
+                 </plugin-repository>`
+        ),
+    {
+      'Content-Type': 'text/xml;charset=UTF-8',
+    }
+  )
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('empty XML')
   .get('/plugin/d/9435.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=9435')
-    .reply(200, '<?xml version="1.0" encoding="UTF-8"?>'), {
-      'Content-Type': 'text/xml;charset=UTF-8'
-    })
-  .expectJSON({ name: 'downloads', value: 'invalid' });
+  .intercept(
+    nock =>
+      nock('https://plugins.jetbrains.com')
+        .get('/plugins/list?pluginId=9435')
+        .reply(200, '<?xml version="1.0" encoding="UTF-8"?>'),
+    {
+      'Content-Type': 'text/xml;charset=UTF-8',
+    }
+  )
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('404 status code')
   .get('/plugin/d/7495.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=7495')
-    .reply(404)
+  .intercept(nock =>
+    nock('https://plugins.jetbrains.com')
+      .get('/plugins/list?pluginId=7495')
+      .reply(404)
   )
-  .expectJSON({ name: 'downloads', value: 'inaccessible' });
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 t.create('empty XML(v)')
   .get('/plugin/v/9435.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=9435')
-    .reply(200, '<?xml version="1.0" encoding="UTF-8"?>'), {
-      'Content-Type': 'text/xml;charset=UTF-8'
-    })
-  .expectJSON({ name: 'jetbrains plugin', value: 'invalid' });
+  .intercept(
+    nock =>
+      nock('https://plugins.jetbrains.com')
+        .get('/plugins/list?pluginId=9435')
+        .reply(200, '<?xml version="1.0" encoding="UTF-8"?>'),
+    {
+      'Content-Type': 'text/xml;charset=UTF-8',
+    }
+  )
+  .expectJSON({ name: 'jetbrains plugin', value: 'invalid' })
 
 t.create('404 status code(v)')
   .get('/plugin/v/7495.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=7495')
-    .reply(404)
+  .intercept(nock =>
+    nock('https://plugins.jetbrains.com')
+      .get('/plugins/list?pluginId=7495')
+      .reply(404)
   )
-  .expectJSON({ name: 'jetbrains plugin', value: 'inaccessible' });
+  .expectJSON({ name: 'jetbrains plugin', value: 'inaccessible' })
 
 t.create('missing required XML element(v)')
   .get('/plugin/v/9435.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=9435')
-    .reply(200, `<?xml version="1.0" encoding="UTF-8"?>
+  .intercept(
+    nock =>
+      nock('https://plugins.jetbrains.com')
+        .get('/plugins/list?pluginId=9435')
+        .reply(
+          200,
+          `<?xml version="1.0" encoding="UTF-8"?>
                  <plugin-repository>
                    <ff>"Code editing"</ff>
                    <category name="Code editing">
                      <!-- no required idea-plugin element here -->
                    </category>
-                 </plugin-repository>`), {
-                   'Content-Type': 'text/xml;charset=UTF-8'
-                 })
-  .expectJSON({ name: 'jetbrains plugin', value: 'invalid' });
+                 </plugin-repository>`
+        ),
+    {
+      'Content-Type': 'text/xml;charset=UTF-8',
+    }
+  )
+  .expectJSON({ name: 'jetbrains plugin', value: 'invalid' })
 
 t.create('incorrect response format (JSON instead of XML)(v)')
   .get('/plugin/v/7495.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=7495')
-    .reply(200, { version: 2.0 })
+  .intercept(nock =>
+    nock('https://plugins.jetbrains.com')
+      .get('/plugins/list?pluginId=7495')
+      .reply(200, { version: 2.0 })
   )
-  .expectJSON({ name: 'jetbrains plugin', value: 'invalid' });
+  .expectJSON({ name: 'jetbrains plugin', value: 'invalid' })
 
 t.create('empty response(v)')
   .get('/plugin/v/7495.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=7495')
-    .reply(200, '')
+  .intercept(nock =>
+    nock('https://plugins.jetbrains.com')
+      .get('/plugins/list?pluginId=7495')
+      .reply(200, '')
   )
-  .expectJSON({ name: 'jetbrains plugin', value: 'invalid' });
+  .expectJSON({ name: 'jetbrains plugin', value: 'invalid' })
 
 t.create('server error(v)')
   .get('/plugin/v/7495.json')
-  .intercept(nock => nock('https://plugins.jetbrains.com')
-    .get('/plugins/list?pluginId=7495')
-    .reply(500)
+  .intercept(nock =>
+    nock('https://plugins.jetbrains.com')
+      .get('/plugins/list?pluginId=7495')
+      .reply(500)
   )
-  .expectJSON({ name: 'jetbrains plugin', value: 'inaccessible' });
+  .expectJSON({ name: 'jetbrains plugin', value: 'inaccessible' })
 
 t.create('connection error(v)')
   .get('/plugin/v/7495.json')
   .networkOff()
-  .expectJSON({ name: 'jetbrains plugin', value: 'inaccessible' });
+  .expectJSON({ name: 'jetbrains plugin', value: 'inaccessible' })
 
 t.create('version for unknown plugin')
   .get('/plugin/v/unknown-plugin.json')
-  .expectJSON({ name: 'jetbrains plugin', value: 'not found' });
+  .expectJSON({ name: 'jetbrains plugin', value: 'not found' })
 
 t.create('version (user friendly plugin id)')
   .get('/plugin/v/1347-scala.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'jetbrains plugin', value: isSemver }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'jetbrains plugin', value: isSemver })
+  )
 
 t.create('version (plugin id from plugin.xml)')
   .get('/plugin/v/org.intellij.scala.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'jetbrains plugin', value: isSemver }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'jetbrains plugin', value: isSemver })
+  )
 
 t.create('version (number as a plugin id)')
   .get('/plugin/v/7495.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'jetbrains plugin', value: isSemver }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'jetbrains plugin', value: isSemver })
+  )
diff --git a/services/jitpack/jitpack.tester.js b/services/jitpack/jitpack.tester.js
index 14bd6d7f73d75dbeb79c8f2789161d1532d019ee..f242ed4145b587199d5663241efe40fe2478a2f1 100644
--- a/services/jitpack/jitpack.tester.js
+++ b/services/jitpack/jitpack.tester.js
@@ -1,28 +1,28 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
 // Github allows versions with chars, etc.
-const isAnyV = Joi.string().regex(/^v.+$/);
+const isAnyV = Joi.string().regex(/^v.+$/)
 
-const t = new ServiceTester({ id: 'jitpack', title: 'JitPack' });
-module.exports = t;
+const t = new ServiceTester({ id: 'jitpack', title: 'JitPack' })
+module.exports = t
 
 t.create('version')
   .get('/v/jitpack/maven-simple.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'JitPack', value: isAnyV }));
+  .expectJSONTypes(Joi.object().keys({ name: 'JitPack', value: isAnyV }))
 
 t.create('unknown package')
   .get('/v/some-bogus-user/project.json')
-  .expectJSON({ name: 'JitPack', value: 'invalid' });
+  .expectJSON({ name: 'JitPack', value: 'invalid' })
 
 t.create('unknown info')
   .get('/z/devtools.json')
   .expectStatus(404)
-  .expectJSON({ name: '404', value: 'badge not found' });
+  .expectJSON({ name: '404', value: 'badge not found' })
 
 t.create('connection error')
   .get('/v/jitpack/maven-simple.json')
   .networkOff()
-  .expectJSON({ name: 'JitPack', value: 'inaccessible' });
+  .expectJSON({ name: 'JitPack', value: 'inaccessible' })
diff --git a/services/json/json.tester.js b/services/json/json.tester.js
index 0f9ca2b6f78640fd284d50fee423b4cf581db9b9..ad9378bb636b070a21837911c92ca4ba7fc50630 100644
--- a/services/json/json.tester.js
+++ b/services/json/json.tester.js
@@ -1,90 +1,163 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const { expect } = require('chai');
-const ServiceTester = require('../service-tester');
-const colorscheme = require('../../lib/colorscheme.json');
-const mapValues = require('lodash.mapvalues');
+const Joi = require('joi')
+const { expect } = require('chai')
+const ServiceTester = require('../service-tester')
+const colorscheme = require('../../lib/colorscheme.json')
+const mapValues = require('lodash.mapvalues')
 
-const colorsB = mapValues(colorscheme, 'colorB');
+const colorsB = mapValues(colorscheme, 'colorB')
 
-const t = new ServiceTester({ id: 'dynamic-json', title: 'User Defined JSON Source Data', pathPrefix: '/badge/dynamic/json' });
-module.exports = t;
+const t = new ServiceTester({
+  id: 'dynamic-json',
+  title: 'User Defined JSON Source Data',
+  pathPrefix: '/badge/dynamic/json',
+})
+module.exports = t
 
 t.create('Connection error')
-  .get('.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.name&label=Package Name&style=_shields_test')
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.name&label=Package Name&style=_shields_test'
+  )
   .networkOff()
-  .expectJSON({ name: 'Package Name', value: 'inaccessible', colorB: colorsB.red });
+  .expectJSON({
+    name: 'Package Name',
+    value: 'inaccessible',
+    colorB: colorsB.red,
+  })
 
 t.create('No URL specified')
   .get('.json?query=$.name&label=Package Name&style=_shields_test')
-  .expectJSON({ name: 'Package Name', value: 'no url specified', colorB: colorsB.red });
+  .expectJSON({
+    name: 'Package Name',
+    value: 'no url specified',
+    colorB: colorsB.red,
+  })
 
 t.create('No query specified')
-  .get('.json?url=https://github.com/badges/shields/raw/master/package.json&label=Package Name&style=_shields_test')
-  .expectJSON({ name: 'Package Name', value: 'no query specified', colorB: colorsB.red });
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/package.json&label=Package Name&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'Package Name',
+    value: 'no query specified',
+    colorB: colorsB.red,
+  })
 
 t.create('Malformed url')
-  .get('.json?url=https://github.com/badges/shields/raw/master/%0package.json&query=$.name&label=Package Name&style=_shields_test')
-  .expectJSON({ name: 'Package Name', value: 'malformed url', colorB: colorsB.red });
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/%0package.json&query=$.name&label=Package Name&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'Package Name',
+    value: 'malformed url',
+    colorB: colorsB.red,
+  })
 
 t.create('JSON from url')
-  .get('.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.name&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'gh-badges', colorB: colorsB.brightgreen });
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.name&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'gh-badges',
+    colorB: colorsB.brightgreen,
+  })
 
 t.create('JSON from uri (support uri query paramater)')
-  .get('.json?uri=https://github.com/badges/shields/raw/master/package.json&query=$.name&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'gh-badges', colorB: colorsB.brightgreen });
+  .get(
+    '.json?uri=https://github.com/badges/shields/raw/master/package.json&query=$.name&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'gh-badges',
+    colorB: colorsB.brightgreen,
+  })
 
 t.create('JSON from url | multiple results')
-  .get('.json?url=https://github.com/badges/shields/raw/master/package.json&query=$..keywords[0:2:1]')
-  .expectJSON({ name: 'custom badge', value: 'GitHub, badge' });
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/package.json&query=$..keywords[0:2:1]'
+  )
+  .expectJSON({ name: 'custom badge', value: 'GitHub, badge' })
 
 t.create('JSON from url | caching with new query params')
-  .get('.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.version')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'custom badge',
-    value: Joi.string().regex(/^\d+(\.\d+)?(\.\d+)?$/)
-  }));
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.version'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'custom badge',
+      value: Joi.string().regex(/^\d+(\.\d+)?(\.\d+)?$/),
+    })
+  )
 
 t.create('JSON from url | with prefix & suffix & label')
-  .get('.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.version&prefix=v&suffix= dev&label=Shields')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'Shields',
-    value: Joi.string().regex(/^v\d+(\.\d+)?(\.\d+)?\sdev$/)
-  }));
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.version&prefix=v&suffix= dev&label=Shields'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'Shields',
+      value: Joi.string().regex(/^v\d+(\.\d+)?(\.\d+)?\sdev$/),
+    })
+  )
 
 t.create('JSON from url | object doesnt exist')
-  .get('.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.does_not_exist&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'no result', colorB: colorsB.lightgrey });
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.does_not_exist&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'no result',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('JSON from url | invalid url')
-  .get('.json?url=https://github.com/badges/shields/raw/master/notafile.json&query=$.version&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'resource not found', colorB: colorsB.lightgrey });
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/notafile.json&query=$.version&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'resource not found',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('JSON from url | user color overrides default')
-  .get('.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.name&colorB=10ADED&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'gh-badges', colorB: '#10ADED' });
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/package.json&query=$.name&colorB=10ADED&style=_shields_test'
+  )
+  .expectJSON({ name: 'custom badge', value: 'gh-badges', colorB: '#10ADED' })
 
 t.create('JSON from url | error color overrides default')
-  .get('.json?url=https://github.com/badges/shields/raw/master/notafile.json&query=$.version&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'resource not found', colorB: colorsB.lightgrey });
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/notafile.json&query=$.version&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'resource not found',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('JSON from url | error color overrides user specified')
   .get('.json?query=$.version&colorB=10ADED&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'no url specified', colorB: colorsB.red });
+  .expectJSON({
+    name: 'custom badge',
+    value: 'no url specified',
+    colorB: colorsB.red,
+  })
 
-let headers;
+let headers
 t.create('JSON from url | request should set Accept header')
   .get('.json?url=https://json-test/api.json&query=$.name')
-  .intercept(nock => nock('https://json-test')
-    .get('/api.json')
-    .reply(200, function (uri, requestBody) {
-      headers = this.req.headers;
-      return '{"name":"test"}';
-    })
+  .intercept(nock =>
+    nock('https://json-test')
+      .get('/api.json')
+      .reply(200, function(uri, requestBody) {
+        headers = this.req.headers
+        return '{"name":"test"}'
+      })
   )
   .expectJSON({ name: 'custom badge', value: 'test' })
-  .after(function () {
-    expect(headers).to.have.property('accept', 'application/json');
-  });
+  .after(function() {
+    expect(headers).to.have.property('accept', 'application/json')
+  })
diff --git a/services/lgtm/lgtm.tester.js b/services/lgtm/lgtm.tester.js
index 5fff9cbf386358fbb40c37af368277a5da3e2cb6..7e5bbb134d4d29a049d0b59b74e722a060e5d0e3 100644
--- a/services/lgtm/lgtm.tester.js
+++ b/services/lgtm/lgtm.tester.js
@@ -1,66 +1,78 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
 const t = new ServiceTester({ id: 'lgtm', title: 'LGTM' })
-module.exports = t;
+module.exports = t
 
 // Alerts Badge
 
 t.create('alerts: total alerts for a project')
   .get('/alerts/g/apache/cloudstack.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'lgtm',
-    value: Joi.string().regex(/^[0-9kM.]+ alerts?$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'lgtm',
+      value: Joi.string().regex(/^[0-9kM.]+ alerts?$/),
+    })
+  )
 
 t.create('alerts: missing project')
   .get('/alerts/g/some-org/this-project-doesnt-exist.json')
   .expectJSON({
     name: 'lgtm',
-    value: 'project not found'
-  });
+    value: 'project not found',
+  })
 
 t.create('alerts: no alerts')
   .get('/alerts/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, {alerts: 0}))
-  .expectJSON({ name: 'lgtm', value: '0 alerts' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, { alerts: 0 })
+  )
+  .expectJSON({ name: 'lgtm', value: '0 alerts' })
 
 t.create('alerts: single alert')
   .get('/alerts/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, {alerts: 1}))
-  .expectJSON({ name: 'lgtm', value: '1 alert' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, { alerts: 1 })
+  )
+  .expectJSON({ name: 'lgtm', value: '1 alert' })
 
 t.create('alerts: multiple alerts')
   .get('/alerts/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, {alerts: 123}))
-  .expectJSON({ name: 'lgtm', value: '123 alerts' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, { alerts: 123 })
+  )
+  .expectJSON({ name: 'lgtm', value: '123 alerts' })
 
 t.create('alerts: json missing alerts')
   .get('/alerts/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, {}))
-  .expectJSON({ name: 'lgtm', value: 'invalid' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, {})
+  )
+  .expectJSON({ name: 'lgtm', value: 'invalid' })
 
 t.create('alerts: invalid json')
   .get('/alerts/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(invalidJSON))
-  .expectJSON({ name: 'lgtm', value: 'invalid' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(invalidJSON)
+  )
+  .expectJSON({ name: 'lgtm', value: 'invalid' })
 
 t.create('alerts: lgtm inaccessible')
   .get('/alerts/g/apache/cloudstack.json')
   .networkOff()
-  .expectJSON({ name: 'lgtm', value: 'inaccessible' });
+  .expectJSON({ name: 'lgtm', value: 'inaccessible' })
 
 // Grade Badge
 
@@ -68,99 +80,121 @@ t.create('grade: missing project')
   .get('/grade/java/g/some-org/this-project-doesnt-exist.json')
   .expectJSON({
     name: 'code quality: java',
-    value: 'project not found'
-  });
+    value: 'project not found',
+  })
 
 t.create('grade: lgtm inaccessible')
   .get('/grade/java/g/apache/cloudstack.json')
   .networkOff()
-  .expectJSON({ name: 'code quality: java', value: 'inaccessible' });
+  .expectJSON({ name: 'code quality: java', value: 'inaccessible' })
 
 t.create('grade: invalid json')
   .get('/grade/java/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(invalidJSON))
-  .expectJSON({ name: 'code quality: java', value: 'invalid' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(invalidJSON)
+  )
+  .expectJSON({ name: 'code quality: java', value: 'invalid' })
 
 t.create('grade: json missing languages')
   .get('/grade/java/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, {}))
-  .expectJSON({ name: 'code quality: java', value: 'invalid' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, {})
+  )
+  .expectJSON({ name: 'code quality: java', value: 'invalid' })
 
 t.create('grade: grade for a project (java)')
   .get('/grade/java/g/apache/cloudstack.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'code quality: java',
-    value: Joi.string().regex(/^(?:A\+)|A|B|C|D|E$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'code quality: java',
+      value: Joi.string().regex(/^(?:A\+)|A|B|C|D|E$/),
+    })
+  )
 
 t.create('grade: grade for missing language')
   .get('/grade/foo/g/apache/cloudstack.json')
   .expectJSON({
     name: 'code quality: foo',
-    value: 'no data for language'
-  });
+    value: 'no data for language',
+  })
 
 // Test display of languages
 
-const data = {languages: [
-  {lang: 'cpp', grade: 'A+'},
-  {lang: 'javascript', grade: 'A'},
-  {lang: 'java', grade: 'B'},
-  {lang: 'python', grade: 'C'},
-  {lang: 'csharp', grade: 'D'},
-  {lang: 'other', grade: 'E'},
-  {lang: 'foo'}
-]}
+const data = {
+  languages: [
+    { lang: 'cpp', grade: 'A+' },
+    { lang: 'javascript', grade: 'A' },
+    { lang: 'java', grade: 'B' },
+    { lang: 'python', grade: 'C' },
+    { lang: 'csharp', grade: 'D' },
+    { lang: 'other', grade: 'E' },
+    { lang: 'foo' },
+  ],
+}
 
 t.create('grade: cpp')
   .get('/grade/cpp/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, data))
-  .expectJSON({ name: 'code quality: c/c++', value: 'A+' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, data)
+  )
+  .expectJSON({ name: 'code quality: c/c++', value: 'A+' })
 
 t.create('grade: javascript')
   .get('/grade/javascript/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, data))
-  .expectJSON({ name: 'code quality: js/ts', value: 'A' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, data)
+  )
+  .expectJSON({ name: 'code quality: js/ts', value: 'A' })
 
 t.create('grade: java')
   .get('/grade/java/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, data))
-  .expectJSON({ name: 'code quality: java', value: 'B' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, data)
+  )
+  .expectJSON({ name: 'code quality: java', value: 'B' })
 
 t.create('grade: python')
   .get('/grade/python/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, data))
-  .expectJSON({ name: 'code quality: python', value: 'C' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, data)
+  )
+  .expectJSON({ name: 'code quality: python', value: 'C' })
 
 t.create('grade: csharp')
   .get('/grade/csharp/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, data))
-  .expectJSON({ name: 'code quality: c#', value: 'D' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, data)
+  )
+  .expectJSON({ name: 'code quality: c#', value: 'D' })
 
 t.create('grade: other')
   .get('/grade/other/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, data))
-  .expectJSON({ name: 'code quality: other', value: 'E' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, data)
+  )
+  .expectJSON({ name: 'code quality: other', value: 'E' })
 
 t.create('grade: foo (no grade for valid language)')
   .get('/grade/foo/g/apache/cloudstack.json')
-  .intercept(nock => nock('https://lgtm.com')
-    .get('/api/v0.1/project/g/apache/cloudstack/details')
-    .reply(200, data))
-  .expectJSON({ name: 'code quality: foo', value: 'no data for language' });
+  .intercept(nock =>
+    nock('https://lgtm.com')
+      .get('/api/v0.1/project/g/apache/cloudstack/details')
+      .reply(200, data)
+  )
+  .expectJSON({ name: 'code quality: foo', value: 'no data for language' })
diff --git a/services/liberapay/liberapay.tester.js b/services/liberapay/liberapay.tester.js
index 1af86de537c4b4a47bd6580b987dd06f81017be5..8bbf7beddc55c33fb2a32c445841cdadacd45551 100644
--- a/services/liberapay/liberapay.tester.js
+++ b/services/liberapay/liberapay.tester.js
@@ -1,53 +1,64 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const isLiberapayTestValues =
-  Joi.string().regex(/^([0-9]*[1-9][0-9]*(\.[0-9]+)?|[0]+\.[0-9]*[1-9][0-9]*)[ A-Za-z]{4}\/week/); //values must be greater than zero
-const {isMetric} = require('../test-validators');
-const t = new ServiceTester({ id: 'liberapay', title: 'Liberapay' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const isLiberapayTestValues = Joi.string().regex(
+  /^([0-9]*[1-9][0-9]*(\.[0-9]+)?|[0]+\.[0-9]*[1-9][0-9]*)[ A-Za-z]{4}\/week/
+) //values must be greater than zero
+const { isMetric } = require('../test-validators')
+const t = new ServiceTester({ id: 'liberapay', title: 'Liberapay' })
+module.exports = t
 
 t.create('Receiving')
   .get('/receives/Liberapay.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'receives',
-    value: isLiberapayTestValues
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'receives',
+      value: isLiberapayTestValues,
+    })
+  )
 
 t.create('Giving')
   .get('/gives/Changaco.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'gives',
-    value: isLiberapayTestValues
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'gives',
+      value: isLiberapayTestValues,
+    })
+  )
 
 t.create('Patrons')
   .get('/patrons/Liberapay.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'patrons',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'patrons',
+      value: isMetric,
+    })
+  )
 
 t.create('Goal Progress')
   .get('/goal/Liberapay.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'goal progress',
-    value: Joi.string().regex(/^[0-9]+%/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'goal progress',
+      value: Joi.string().regex(/^[0-9]+%/),
+    })
+  )
 
 t.create('No Goal')
   .get('/goal/Liberapay.json')
-  .intercept(nock => nock('https://liberapay.com')
-    .get('/Liberapay/public.json')
-    .reply(200, { goal: null })
+  .intercept(nock =>
+    nock('https://liberapay.com')
+      .get('/Liberapay/public.json')
+      .reply(200, { goal: null })
   )
-  .expectJSON({ name: 'goal progress', value: 'anonymous'});
+  .expectJSON({ name: 'goal progress', value: 'anonymous' })
 
 t.create('Empty')
   .get('/receives/Liberapay.json')
-  .intercept(nock => nock('https://liberapay.com')
-    .get('/Liberapay/public.json')
-    .reply(200, { receiving: 0.00 })
+  .intercept(nock =>
+    nock('https://liberapay.com')
+      .get('/Liberapay/public.json')
+      .reply(200, { receiving: 0.0 })
   )
-  .expectJSON({ name: 'receives', value: 'anonymous'});
+  .expectJSON({ name: 'receives', value: 'anonymous' })
diff --git a/services/librariesio/librariesio.tester.js b/services/librariesio/librariesio.tester.js
index db4a78b3ae821af79f5d352eecc09b5059fffa15..395c81aefec4a3e5d20bee89f28350bf055d873b 100644
--- a/services/librariesio/librariesio.tester.js
+++ b/services/librariesio/librariesio.tester.js
@@ -1,41 +1,45 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const {
-  isDependencyState
-} = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isDependencyState } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'librariesio', title: 'Libraries.io' });
-module.exports = t;
+const t = new ServiceTester({ id: 'librariesio', title: 'Libraries.io' })
+module.exports = t
 
 t.create('dependencies for releases')
   .get('/release/hex/phoenix/1.0.3.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'dependencies',
-    value: isDependencyState,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'dependencies',
+      value: isDependencyState,
+    })
+  )
 
 t.create('dependencies for github')
   .get('/github/pyvesb/notepad4e.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'dependencies',
-    value: isDependencyState,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'dependencies',
+      value: isDependencyState,
+    })
+  )
 
 t.create('release not found')
   .get('/release/hex/invalid/4.0.4.json')
   .expectJSON({
     name: 'dependencies',
     value: 'not available',
-  });
+  })
 
 t.create('no response data')
   .get('/github/phoenixframework/phoenix.json')
-  .intercept(nock => nock('https://libraries.io')
-    .get('/api/github/phoenixframework/phoenix/dependencies')
-    .reply(200))
+  .intercept(nock =>
+    nock('https://libraries.io')
+      .get('/api/github/phoenixframework/phoenix/dependencies')
+      .reply(200)
+  )
   .expectJSON({
-     name: 'dependencies',
-     value: 'invalid',
-  });
+    name: 'dependencies',
+    value: 'invalid',
+  })
diff --git a/services/libscore/libscore.tester.js b/services/libscore/libscore.tester.js
index 67d4486d903fcc06dafbad17cb366dd9cfc81dc0..edd15ee8dd22a195b7d9e0c9686a4764ad7c3992 100644
--- a/services/libscore/libscore.tester.js
+++ b/services/libscore/libscore.tester.js
@@ -1,41 +1,45 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isMetric } = require('../test-validators');
-const { invalidJSON } = require('../response-fixtures');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isMetric } = require('../test-validators')
+const { invalidJSON } = require('../response-fixtures')
 
-const t = new ServiceTester({ id: 'libscore', title: 'libscore' });
-module.exports = t;
+const t = new ServiceTester({ id: 'libscore', title: 'libscore' })
+module.exports = t
 
 t.create('libscore (valid)')
   .get('/s/jQuery.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'libscore',
-    value: isMetric,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'libscore',
+      value: isMetric,
+    })
+  )
 
 t.create('libscore (not found)')
   .get('/s/not-a-library.json')
-  .expectJSON({name: 'libscore', value: 'not found'});
+  .expectJSON({ name: 'libscore', value: 'not found' })
 
 t.create('libscore (connection error)')
   .get('/s/jQuery.json')
   .networkOff()
-  .expectJSON({name: 'libscore', value: 'inaccessible'});
+  .expectJSON({ name: 'libscore', value: 'inaccessible' })
 
 t.create('libscore (unexpected response)')
   .get('/s/jQuery.json')
-  .intercept(nock => nock('http://api.libscore.com')
-    .get('/v1/libraries/jQuery')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('http://api.libscore.com')
+      .get('/v1/libraries/jQuery')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'libscore', value: 'invalid'});
+  .expectJSON({ name: 'libscore', value: 'invalid' })
 
 t.create('libscore (error response)')
   .get('/s/jQuery.json')
-  .intercept(nock => nock('http://api.libscore.com')
-    .get('/v1/libraries/jQuery')
-    .reply(500, '{"error":"oh noes!!"}')
+  .intercept(nock =>
+    nock('http://api.libscore.com')
+      .get('/v1/libraries/jQuery')
+      .reply(500, '{"error":"oh noes!!"}')
   )
-  .expectJSON({name: 'libscore', value: 'invalid'});
+  .expectJSON({ name: 'libscore', value: 'invalid' })
diff --git a/services/luarocks/luarocks.tester.js b/services/luarocks/luarocks.tester.js
index 1279ff4d4ac618626d4f94d2c366b9328ae1d06e..19907808c5a7fd475af4a4265eac1674acbe03c1 100644
--- a/services/luarocks/luarocks.tester.js
+++ b/services/luarocks/luarocks.tester.js
@@ -1,25 +1,27 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'luarocks', title: 'LuaRocks' });
-module.exports = t;
+const t = new ServiceTester({ id: 'luarocks', title: 'LuaRocks' })
+module.exports = t
 
-const isLuaVersion = Joi.string().regex(/^v\d+\.\d+\.\d+-\d+$/);
+const isLuaVersion = Joi.string().regex(/^v\d+\.\d+\.\d+-\d+$/)
 
 t.create('version')
   .get('/v/mpeterv/luacheck.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'luarocks',
-    value: isLuaVersion
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'luarocks',
+      value: isLuaVersion,
+    })
+  )
 
 t.create('unknown package')
   .get('/v/nil/does-not-exist.json')
-  .expectJSON({ name: 'luarocks', value: 'invalid' });
+  .expectJSON({ name: 'luarocks', value: 'invalid' })
 
 t.create('connection error')
   .get('/v/mpeterv/luacheck.json')
   .networkOff()
-  .expectJSON({ name: 'luarocks', value: 'inaccessible' });
+  .expectJSON({ name: 'luarocks', value: 'inaccessible' })
diff --git a/services/magnumci/magnumci.tester.js b/services/magnumci/magnumci.tester.js
index 5df50eeb059bcef0c0208d97026913eed43df1a1..3b75f3e203c1d94794da40a60558722b1419a77a 100644
--- a/services/magnumci/magnumci.tester.js
+++ b/services/magnumci/magnumci.tester.js
@@ -1,13 +1,13 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'magnumci', title: 'Magnum CI' });
-module.exports = t;
+const t = new ServiceTester({ id: 'magnumci', title: 'Magnum CI' })
+module.exports = t
 
 t.create('no longer available')
   .get('/ci/96ffb83fa700f069024921b0702e76ff.json')
   .expectJSON({
     name: 'magnum ci',
-    value: 'no longer available'
-  });
+    value: 'no longer available',
+  })
diff --git a/services/maintenance/maintenance.tester.js b/services/maintenance/maintenance.tester.js
index 7c7348848690fade4464b0e6573ce13ce0f2ee7c..9f3a9edac3007fb4a238b43e3ab88ae6ae24b24e 100644
--- a/services/maintenance/maintenance.tester.js
+++ b/services/maintenance/maintenance.tester.js
@@ -1,24 +1,24 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'maintenance', title: 'Maintenance' });
-module.exports = t;
+const t = new ServiceTester({ id: 'maintenance', title: 'Maintenance' })
+module.exports = t
 
-const currentYear = (new Date()).getUTCFullYear();
+const currentYear = new Date().getUTCFullYear()
 
 t.create('yes last maintained 2016 (no)')
   .get('/yes/2016.json')
-  .expectJSON({ name: 'maintained', value: 'no! (as of 2016)' });
+  .expectJSON({ name: 'maintained', value: 'no! (as of 2016)' })
 
 t.create('no longer maintained 2017 (no)')
   .get('/no/2017.json')
-  .expectJSON({ name: 'maintained', value: 'no! (as of 2017)' });
+  .expectJSON({ name: 'maintained', value: 'no! (as of 2017)' })
 
 t.create('yes this year (yes)')
   .get('/yes/' + currentYear + '.json')
-  .expectJSON({ name: 'maintained', value: 'yes' });
+  .expectJSON({ name: 'maintained', value: 'yes' })
 
 t.create('until end of ' + currentYear + ' (yes)')
   .get('/until end of ' + currentYear + '/' + currentYear + '.json')
-  .expectJSON({ name: 'maintained', value: 'until end of ' + currentYear });
+  .expectJSON({ name: 'maintained', value: 'until end of ' + currentYear })
diff --git a/services/maven-central/maven-central.tester.js b/services/maven-central/maven-central.tester.js
index f1ceae2d55050a8ae00db866cf85879a2a1a19c9..2125abfe5f5de637ddfbabb6debb128038ac43ae 100644
--- a/services/maven-central/maven-central.tester.js
+++ b/services/maven-central/maven-central.tester.js
@@ -1,37 +1,43 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'maven-central', title: 'Maven Central' });
-module.exports = t;
+const t = new ServiceTester({ id: 'maven-central', title: 'Maven Central' })
+module.exports = t
 
 t.create('latest version')
   .get('/v/com.github.fabriziocucci/yacl4j.json') // http://repo1.maven.org/maven2/com/github/fabriziocucci/yacl4j/
-  .expectJSONTypes(Joi.object().keys({
-    name: 'maven-central',
-    value: Joi.string().regex(/^v(.*)$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'maven-central',
+      value: Joi.string().regex(/^v(.*)$/),
+    })
+  )
 
 t.create('latest 0.8 version')
   .get('/v/com.github.fabriziocucci/yacl4j/0.8.json') // http://repo1.maven.org/maven2/com/github/fabriziocucci/yacl4j/
-  .expectJSONTypes(Joi.object().keys({
-    name: 'maven-central',
-    value: Joi.string().regex(/^v0\.8(.*)$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'maven-central',
+      value: Joi.string().regex(/^v0\.8(.*)$/),
+    })
+  )
 
 t.create('inexistent artifact')
   .get('/v/inexistent-group-id/inexistent-artifact-id.json')
-  .expectJSON({ name: 'maven-central', value: 'invalid' });
+  .expectJSON({ name: 'maven-central', value: 'invalid' })
 
 t.create('connection error')
   .get('/v/com.github.fabriziocucci/yacl4j.json')
   .networkOff()
-  .expectJSON({ name: 'maven-central', value: 'inaccessible' });
+  .expectJSON({ name: 'maven-central', value: 'inaccessible' })
 
 t.create('xml parsing error')
   .get('/v/com.github.fabriziocucci/yacl4j.json')
-  .intercept(nock => nock('http://repo1.maven.org/maven2')
-    .get('/com/github/fabriziocucci/yacl4j/maven-metadata.xml')
-    .reply(200, 'this should be a valid xml'))
-  .expectJSON({ name: 'maven-central', value: 'invalid' });
+  .intercept(nock =>
+    nock('http://repo1.maven.org/maven2')
+      .get('/com/github/fabriziocucci/yacl4j/maven-metadata.xml')
+      .reply(200, 'this should be a valid xml')
+  )
+  .expectJSON({ name: 'maven-central', value: 'invalid' })
diff --git a/services/maven-metadata/maven-metadata.tester.js b/services/maven-metadata/maven-metadata.tester.js
index 07b7afff2373203d4cc7b394d47ddefbaab0ab9f..0ca9405191698f883c3f4047b72aee9bd227ecdb 100644
--- a/services/maven-metadata/maven-metadata.tester.js
+++ b/services/maven-metadata/maven-metadata.tester.js
@@ -1,15 +1,22 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'maven-metadata', title: 'maven-metadata badge' });
-module.exports = t;
+const t = new ServiceTester({
+  id: 'maven-metadata',
+  title: 'maven-metadata badge',
+})
+module.exports = t
 
 t.create('valid maven-metadata.xml uri')
-  .get('/v/http/central.maven.org/maven2/com/google/code/gson/gson/maven-metadata.xml.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'maven',
-    value: isVPlusDottedVersionAtLeastOne
-  }));
+  .get(
+    '/v/http/central.maven.org/maven2/com/google/code/gson/gson/maven-metadata.xml.json'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'maven',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
diff --git a/services/microbadger/microbadger.tester.js b/services/microbadger/microbadger.tester.js
index 208c5220f51258891f19a44d8ddc29fc604987a4..376ba4fac178d6df846d5de3dbb0d24f3f24f9df 100644
--- a/services/microbadger/microbadger.tester.js
+++ b/services/microbadger/microbadger.tester.js
@@ -1,86 +1,103 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isFileSize } = require('../test-validators');
-const { invalidJSON } = require('../response-fixtures');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isFileSize } = require('../test-validators')
+const { invalidJSON } = require('../response-fixtures')
 
-const t = new ServiceTester({ id: 'microbadger', title: 'MicroBadger' });
-module.exports = t;
+const t = new ServiceTester({ id: 'microbadger', title: 'MicroBadger' })
+module.exports = t
 
 t.create('image size without a specified tag')
   .get('/image-size/wikiwi/docker-build.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'image size',
-    value: isFileSize
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'image size',
+      value: isFileSize,
+    })
+  )
 
 t.create('image size with a specified tag')
   .get('/image-size/kelseyhightower/helloworld/appengine.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'image size',
-    value: isFileSize
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'image size',
+      value: isFileSize,
+    })
+  )
 
 t.create('layers without a specified tag')
   .get('/layers/_/hello-world.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'layers',
-    value: Joi.number().integer().positive()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'layers',
+      value: Joi.number()
+        .integer()
+        .positive(),
+    })
+  )
 
 t.create('layers with a specified tag')
   .get('/layers/_/httpd/alpine.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'layers',
-    value: Joi.number().integer().positive()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'layers',
+      value: Joi.number()
+        .integer()
+        .positive(),
+    })
+  )
 
 t.create('specified tag when repository has only one')
   .get('/layers/_/hello-world/wrong-tag.json')
-  .expectJSON({ name: 'layers', value: 'not found' });
+  .expectJSON({ name: 'layers', value: 'not found' })
 
 t.create('nonexistent repository')
   .get('/layers/_/unknown.json')
-  .intercept(nock => nock('https://api.microbadger.com')
-    .get('/v1/images/library/unknown')
-    .reply(404)
+  .intercept(nock =>
+    nock('https://api.microbadger.com')
+      .get('/v1/images/library/unknown')
+      .reply(404)
   )
-  .expectJSON({ name: 'layers', value: 'not found' });
+  .expectJSON({ name: 'layers', value: 'not found' })
 
 t.create('nonexistent tag')
   .get('/layers/_/unknown/wrong-tag.json')
-  .intercept(nock => nock('https://api.microbadger.com')
-    .get('/v1/images/library/unknown')
-    .reply(200, { Versions: [] })
+  .intercept(nock =>
+    nock('https://api.microbadger.com')
+      .get('/v1/images/library/unknown')
+      .reply(200, { Versions: [] })
   )
-  .expectJSON({ name: 'layers', value: 'not found' });
+  .expectJSON({ name: 'layers', value: 'not found' })
 
 t.create('server error')
   .get('/image-size/_/hello-world.json')
-  .intercept(nock => nock('https://api.microbadger.com')
-    .get('/v1/images/library/hello-world')
-    .reply(500, 'Something went wrong')
+  .intercept(nock =>
+    nock('https://api.microbadger.com')
+      .get('/v1/images/library/hello-world')
+      .reply(500, 'Something went wrong')
   )
-  .expectJSON({ name: 'image size', value: 'inaccessible' });
+  .expectJSON({ name: 'image size', value: 'inaccessible' })
 
 t.create('connection error')
   .get('/image-size/_/hello-world.json')
   .networkOff()
-  .expectJSON({ name: 'image size', value: 'inaccessible' });
+  .expectJSON({ name: 'image size', value: 'inaccessible' })
 
 t.create('unexpected response')
   .get('/image-size/_/hello-world.json')
-  .intercept(nock => nock('https://api.microbadger.com')
-    .get('/v1/images/library/hello-world')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.microbadger.com')
+      .get('/v1/images/library/hello-world')
+      .reply(invalidJSON)
   )
-  .expectJSON({ name: 'image size', value: 'error' });
+  .expectJSON({ name: 'image size', value: 'error' })
 
 t.create('missing download size')
   .get('/image-size/puppet/puppetserver.json')
-  .intercept(nock => nock('https://api.microbadger.com')
-    .get('/v1/images/puppet/puppetserver')
-    .reply(200, {})
+  .intercept(nock =>
+    nock('https://api.microbadger.com')
+      .get('/v1/images/puppet/puppetserver')
+      .reply(200, {})
   )
-  .expectJSON({ name: 'image size', value: 'unknown' });
+  .expectJSON({ name: 'image size', value: 'unknown' })
diff --git a/services/myget/myget.tester.js b/services/myget/myget.tester.js
index 3b1987854a3fe2115108b7dc0430429ca5290d81..6f58c89748853859979de5390bb5b10fb3bde6ae 100644
--- a/services/myget/myget.tester.js
+++ b/services/myget/myget.tester.js
@@ -1,233 +1,257 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isMetric,
   isVPlusDottedVersionNClauses,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators');
-const colorscheme = require('../../lib/colorscheme.json');
+} = require('../test-validators')
+const colorscheme = require('../../lib/colorscheme.json')
 const {
   queryIndex,
   nuGetV3VersionJsonWithDash,
   nuGetV3VersionJsonFirstCharZero,
   nuGetV3VersionJsonFirstCharNotZero,
-} = require('../nuget-fixtures');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'myget', title: 'MyGet' });
-module.exports = t;
+} = require('../nuget-fixtures')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'myget', title: 'MyGet' })
+module.exports = t
 
 // downloads
 
 t.create('total downloads (valid)')
   .get('/mongodb/dt/MongoDB.Driver.Core.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('total downloads (not found)')
   .get('/mongodb/dt/not-a-real-package.json')
-  .expectJSON({name: 'downloads', value: 'not found'});
+  .expectJSON({ name: 'downloads', value: 'not found' })
 
 t.create('total downloads (connection error)')
   .get('/mongodb/dt/MongoDB.Driver.Core.json')
   .networkOff()
-  .expectJSON({name: 'downloads', value: 'inaccessible'});
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 t.create('total downloads (unexpected first response)')
   .get('/mongodb/dt/MongoDB.Driver.Core.json')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'downloads', value: 'invalid'});
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('total downloads (unexpected second response)')
   .get('/mongodb/dt/MongoDB.Driver.Core.json')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:mongodb.driver.core&prerelease=true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:mongodb.driver.core&prerelease=true')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'downloads', value: 'invalid'});
-
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 // version
 
 t.create('version (valid)')
   .get('/mongodb/v/MongoDB.Driver.Core.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'mongodb',
-    value: isVPlusDottedVersionNClauses,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'mongodb',
+      value: isVPlusDottedVersionNClauses,
+    })
+  )
 
 t.create('version (mocked, yellow badge)')
   .get('/mongodb/v/MongoDB.Driver.Core.json?style=_shields_test')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:mongodb.driver.core&prerelease=true")
-    .reply(200, nuGetV3VersionJsonWithDash)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:mongodb.driver.core&prerelease=true')
+      .reply(200, nuGetV3VersionJsonWithDash)
   )
   .expectJSON({
     name: 'mongodb',
     value: 'v1.2-beta',
-    colorB: colorscheme.yellow.colorB
-  });
+    colorB: colorscheme.yellow.colorB,
+  })
 
 t.create('version (mocked, orange badge)')
   .get('/mongodb/v/MongoDB.Driver.Core.json?style=_shields_test')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:mongodb.driver.core&prerelease=true")
-    .reply(200, nuGetV3VersionJsonFirstCharZero)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:mongodb.driver.core&prerelease=true')
+      .reply(200, nuGetV3VersionJsonFirstCharZero)
   )
   .expectJSON({
     name: 'mongodb',
     value: 'v0.35',
-    colorB: colorscheme.orange.colorB
-  });
+    colorB: colorscheme.orange.colorB,
+  })
 
 t.create('version (mocked, blue badge)')
   .get('/mongodb/v/MongoDB.Driver.Core.json?style=_shields_test')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:mongodb.driver.core&prerelease=true")
-    .reply(200, nuGetV3VersionJsonFirstCharNotZero)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:mongodb.driver.core&prerelease=true')
+      .reply(200, nuGetV3VersionJsonFirstCharNotZero)
   )
   .expectJSON({
     name: 'mongodb',
     value: 'v1.2.7',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('version (not found)')
   .get('/foo/v/not-a-real-package.json')
-  .expectJSON({name: 'foo', value: 'not found'});
+  .expectJSON({ name: 'foo', value: 'not found' })
 
 t.create('version (connection error)')
   .get('/mongodb/v/MongoDB.Driver.Core.json')
   .networkOff()
-  .expectJSON({name: 'mongodb', value: 'inaccessible'});
+  .expectJSON({ name: 'mongodb', value: 'inaccessible' })
 
 t.create('version (unexpected first response)')
   .get('/mongodb/v/MongoDB.Driver.Core.json')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'mongodb', value: 'invalid'});
+  .expectJSON({ name: 'mongodb', value: 'invalid' })
 
 t.create('version (unexpected second response)')
   .get('/mongodb/v/MongoDB.Driver.Core.json')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:mongodb.driver.core&prerelease=true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:mongodb.driver.core&prerelease=true')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'mongodb', value: 'invalid'});
-
+  .expectJSON({ name: 'mongodb', value: 'invalid' })
 
 // version (pre)
 
 t.create('version (pre) (valid)')
   .get('/mongodb/vpre/MongoDB.Driver.Core.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'mongodb',
-    value: isVPlusDottedVersionNClausesWithOptionalSuffix,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'mongodb',
+      value: isVPlusDottedVersionNClausesWithOptionalSuffix,
+    })
+  )
 
 t.create('version (pre) (mocked, yellow badge)')
   .get('/mongodb/vpre/MongoDB.Driver.Core.json?style=_shields_test')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:mongodb.driver.core&prerelease=true")
-    .reply(200, nuGetV3VersionJsonWithDash)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:mongodb.driver.core&prerelease=true')
+      .reply(200, nuGetV3VersionJsonWithDash)
   )
   .expectJSON({
     name: 'mongodb',
     value: 'v1.2-beta',
-    colorB: colorscheme.yellow.colorB
-  });
+    colorB: colorscheme.yellow.colorB,
+  })
 
 t.create('version (pre) (mocked, orange badge)')
   .get('/mongodb/vpre/MongoDB.Driver.Core.json?style=_shields_test')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:mongodb.driver.core&prerelease=true")
-    .reply(200, nuGetV3VersionJsonFirstCharZero)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:mongodb.driver.core&prerelease=true')
+      .reply(200, nuGetV3VersionJsonFirstCharZero)
   )
   .expectJSON({
     name: 'mongodb',
     value: 'v0.35',
-    colorB: colorscheme.orange.colorB
-  });
+    colorB: colorscheme.orange.colorB,
+  })
 
 t.create('version (pre) (mocked, blue badge)')
   .get('/mongodb/vpre/MongoDB.Driver.Core.json?style=_shields_test')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:mongodb.driver.core&prerelease=true")
-    .reply(200, nuGetV3VersionJsonFirstCharNotZero)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:mongodb.driver.core&prerelease=true')
+      .reply(200, nuGetV3VersionJsonFirstCharNotZero)
   )
   .expectJSON({
     name: 'mongodb',
     value: 'v1.2.7',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('version (pre) (not found)')
   .get('/foo/vpre/not-a-real-package.json')
-  .expectJSON({name: 'foo', value: 'not found'});
+  .expectJSON({ name: 'foo', value: 'not found' })
 
 t.create('version (pre) (connection error)')
   .get('/mongodb/vpre/MongoDB.Driver.Core.json')
   .networkOff()
-  .expectJSON({name: 'mongodb', value: 'inaccessible'});
+  .expectJSON({ name: 'mongodb', value: 'inaccessible' })
 
 t.create('version (pre) (unexpected first response)')
   .get('/mongodb/vpre/MongoDB.Driver.Core.json')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'mongodb', value: 'invalid'});
+  .expectJSON({ name: 'mongodb', value: 'invalid' })
 
 t.create('version (pre) (unexpected second response)')
   .get('/mongodb/vpre/MongoDB.Driver.Core.json')
-  .intercept(nock => nock('https://www.myget.org')
-    .get("/F/mongodb/api/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://www.myget.org')
+      .get('/F/mongodb/api/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:mongodb.driver.core&prerelease=true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:mongodb.driver.core&prerelease=true')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'mongodb', value: 'invalid'});
+  .expectJSON({ name: 'mongodb', value: 'invalid' })
diff --git a/services/nexus/nexus.tester.js b/services/nexus/nexus.tester.js
index e19eaf77fb970770bd8931ce4d90372cfc9ac0a9..4d7c39a5f75802735593da55cd553b8a67e08934 100644
--- a/services/nexus/nexus.tester.js
+++ b/services/nexus/nexus.tester.js
@@ -1,74 +1,89 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
 
-const t = new ServiceTester({ id: 'nexus', title: 'Nexus' });
-module.exports = t;
+const t = new ServiceTester({ id: 'nexus', title: 'Nexus' })
+module.exports = t
 
 t.create('search release version')
   .get('/r/https/repository.jboss.org/nexus/jboss/jboss-client.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'nexus',
-    value: Joi.string().regex(/^v4(\.\d+)+$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'nexus',
+      value: Joi.string().regex(/^v4(\.\d+)+$/),
+    })
+  )
 
 t.create('search release version of an inexistent artifact')
   .get('/r/https/repository.jboss.org/nexus/jboss/inexistent-artifact-id.json')
-  .expectJSON({ name: 'nexus', value: 'no-artifact' });
+  .expectJSON({ name: 'nexus', value: 'no-artifact' })
 
 t.create('search snapshot version')
   .get('/s/https/repository.jboss.org/nexus/com.progress.fuse/fusehq.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'nexus',
-    value: Joi.string().regex(/-SNAPSHOT$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'nexus',
+      value: Joi.string().regex(/-SNAPSHOT$/),
+    })
+  )
 
 t.create('search snapshot version not in latestSnapshot')
   .get('/s/https/repository.jboss.org/nexus/com.progress.fuse/fusehq.json')
-  .intercept(nock => nock('https://repository.jboss.org')
-    .get('/nexus/service/local/lucene/search')
-    .query({g: 'com.progress.fuse', a: 'fusehq'})
-    .reply(200, '{ "data": [ { "version": "7.0.1-SNAPSHOT" } ] }'))
-  .expectJSON({ name: 'nexus', value: 'v7.0.1-SNAPSHOT' });
+  .intercept(nock =>
+    nock('https://repository.jboss.org')
+      .get('/nexus/service/local/lucene/search')
+      .query({ g: 'com.progress.fuse', a: 'fusehq' })
+      .reply(200, '{ "data": [ { "version": "7.0.1-SNAPSHOT" } ] }')
+  )
+  .expectJSON({ name: 'nexus', value: 'v7.0.1-SNAPSHOT' })
 
 t.create('search snapshot version of a release artifact')
   .get('/s/https/repository.jboss.org/nexus/jboss/jboss-client.json')
-  .expectJSON({ name: 'nexus', value: 'undefined' });
+  .expectJSON({ name: 'nexus', value: 'undefined' })
 
 t.create('search snapshot version of an inexistent artifact')
   .get('/s/https/repository.jboss.org/nexus/jboss/inexistent-artifact-id.json')
-  .expectJSON({ name: 'nexus', value: 'no-artifact' });
+  .expectJSON({ name: 'nexus', value: 'no-artifact' })
 
 t.create('resolve version')
   .get('/developer/https/repository.jboss.org/nexus/ai.h2o/h2o-automl.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'nexus',
-    value: Joi.string().regex(/^v3(\.\d+)+$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'nexus',
+      value: Joi.string().regex(/^v3(\.\d+)+$/),
+    })
+  )
 
 t.create('resolve version with query')
-  .get('/fs-public-snapshots/https/repository.jboss.org/nexus/com.progress.fuse/fusehq:c=agent-apple-osx:p=tar.gz.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'nexus',
-    value: Joi.string().regex(/^v7(\.\d+)+-SNAPSHOT$/)
-  }));
+  .get(
+    '/fs-public-snapshots/https/repository.jboss.org/nexus/com.progress.fuse/fusehq:c=agent-apple-osx:p=tar.gz.json'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'nexus',
+      value: Joi.string().regex(/^v7(\.\d+)+-SNAPSHOT$/),
+    })
+  )
 
 t.create('resolve version of an inexistent artifact')
-  .get('/developer/https/repository.jboss.org/nexus/jboss/inexistent-artifact-id.json')
-  .expectJSON({ name: 'nexus', value: 'no-artifact' });
+  .get(
+    '/developer/https/repository.jboss.org/nexus/jboss/inexistent-artifact-id.json'
+  )
+  .expectJSON({ name: 'nexus', value: 'no-artifact' })
 
 t.create('connection error')
   .get('/r/https/repository.jboss.org/nexus/jboss/jboss-client.json')
   .networkOff()
-  .expectJSON({ name: 'nexus', value: 'inaccessible' });
+  .expectJSON({ name: 'nexus', value: 'inaccessible' })
 
 t.create('json parsing error')
   .get('/r/https/repository.jboss.org/nexus/jboss/jboss-client.json')
-  .intercept(nock => nock('https://repository.jboss.org')
-    .get('/nexus/service/local/lucene/search')
-    .query({g: 'jboss', a: 'jboss-client'})
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://repository.jboss.org')
+      .get('/nexus/service/local/lucene/search')
+      .query({ g: 'jboss', a: 'jboss-client' })
+      .reply(invalidJSON)
   )
-  .expectJSON({ name: 'nexus', value: 'invalid' });
+  .expectJSON({ name: 'nexus', value: 'invalid' })
diff --git a/services/node/node-version-color.js b/services/node/node-version-color.js
index 9e51fea1ca85d080f8cd8c3a06b857a3fafb27bb..5c1a5abf735a4be3b1cd4141344b5c9548da5d8f 100644
--- a/services/node/node-version-color.js
+++ b/services/node/node-version-color.js
@@ -1,37 +1,37 @@
-'use strict';
+'use strict'
 
-const { promisify } = require('util');
-const semver = require('semver');
-const { regularUpdate } = require('../../lib/regular-update');
+const { promisify } = require('util')
+const semver = require('semver')
+const { regularUpdate } = require('../../lib/regular-update')
 
-function getLatestVersion () {
+function getLatestVersion() {
   return promisify(regularUpdate)({
     url: 'https://nodejs.org/dist/latest/SHASUMS256.txt',
     intervalMillis: 24 * 3600 * 1000,
     json: false,
     scraper: shasums => {
       // tarball index start, tarball index end
-      const taris = shasums.indexOf('node-v');
-      const tarie = shasums.indexOf('\n', taris);
-      const tarball = shasums.slice(taris, tarie);
-      const version = tarball.split('-')[1];
-      return version;
+      const taris = shasums.indexOf('node-v')
+      const tarie = shasums.indexOf('\n', taris)
+      const tarball = shasums.slice(taris, tarie)
+      const version = tarball.split('-')[1]
+      return version
     },
-  });
+  })
 }
 
 async function versionColorForRange(range) {
-  const latestVersion = await getLatestVersion();
+  const latestVersion = await getLatestVersion()
   try {
     if (semver.satisfies(latestVersion, range)) {
-      return 'brightgreen';
+      return 'brightgreen'
     } else if (semver.gtr(latestVersion, range)) {
-      return 'yellow';
+      return 'yellow'
     } else {
-      return 'orange';
+      return 'orange'
     }
-  } catch(e) {
-    return 'lightgray';
+  } catch (e) {
+    return 'lightgray'
   }
 }
 
diff --git a/services/node/node.service.js b/services/node/node.service.js
index e51c317bcfe138b7da2d027ddcb73e6b465be8ff..460d6ee13e7dc7c13a5055ce93c3a3fc5208ef36 100644
--- a/services/node/node.service.js
+++ b/services/node/node.service.js
@@ -1,19 +1,19 @@
-'use strict';
+'use strict'
 
-const NPMBase = require('../npm/npm-base');
-const { versionColorForRange } = require('./node-version-color');
+const NPMBase = require('../npm/npm-base')
+const { versionColorForRange } = require('./node-version-color')
 
 module.exports = class NodeVersion extends NPMBase {
   static get category() {
-    return 'version';
+    return 'version'
   }
 
   static get defaultBadgeData() {
-    return { label: 'node' };
+    return { label: 'node' }
   }
 
   static get url() {
-    return this.buildUrl('node/v', { withTag: true });
+    return this.buildUrl('node/v', { withTag: true })
   }
 
   static get examples() {
@@ -43,24 +43,24 @@ module.exports = class NodeVersion extends NPMBase {
         query: { registry_uri: 'https://registry.npmjs.com' },
         keywords: ['npm'],
       },
-    ];
+    ]
   }
 
   static async render({ tag, nodeVersionRange }) {
-    const label = tag ? `node@${tag}` : undefined;
+    const label = tag ? `node@${tag}` : undefined
 
     if (nodeVersionRange === undefined) {
       return {
         label,
         message: 'not specified',
         color: 'lightgray',
-      };
+      }
     } else {
       return {
         label,
         message: nodeVersionRange,
         color: await versionColorForRange(nodeVersionRange),
-      };
+      }
     }
   }
 
@@ -70,16 +70,16 @@ module.exports = class NodeVersion extends NPMBase {
       packageName,
       tag,
       registryUrl,
-    } = this.constructor.unpackParams(namedParams, queryParams);
+    } = this.constructor.unpackParams(namedParams, queryParams)
     const { engines } = await this.fetchPackageData({
       scope,
       packageName,
       registryUrl,
       tag,
-    });
+    })
 
-    const { node: nodeVersionRange } = engines || {};
+    const { node: nodeVersionRange } = engines || {}
 
-    return this.constructor.render({ tag, nodeVersionRange });
+    return this.constructor.render({ tag, nodeVersionRange })
   }
-};
+}
diff --git a/services/node/node.tester.js b/services/node/node.tester.js
index 973fda0517cd4b828603e0c172dc9c76b7fdceab..df986725476f7ac14ad108fc5a20fffc8ceaecdc 100644
--- a/services/node/node.tester.js
+++ b/services/node/node.tester.js
@@ -1,42 +1,52 @@
-'use strict';
+'use strict'
 
-const { expect } = require('chai');
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { Range } = require('semver');
+const { expect } = require('chai')
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { Range } = require('semver')
 
-const t = new ServiceTester({ id: 'node', title: 'Node' });
-module.exports = t;
+const t = new ServiceTester({ id: 'node', title: 'Node' })
+module.exports = t
 
 function expectSemverRange(value) {
-  expect(() => new Range(value)).not.to.throw();
+  expect(() => new Range(value)).not.to.throw()
 }
 
 t.create('gets the node version of passport')
   .get('/v/passport.json')
   .expectJSONTypes(Joi.object({ name: 'node' }).unknown())
-  .afterJSON(json => { expectSemverRange(json.value); });
+  .afterJSON(json => {
+    expectSemverRange(json.value)
+  })
 
 t.create('gets the node version of @stdlib/stdlib')
   .get('/v/@stdlib/stdlib.json')
   .expectJSONTypes(Joi.object({ name: 'node' }).unknown())
-  .afterJSON(json => { expectSemverRange(json.value); });
+  .afterJSON(json => {
+    expectSemverRange(json.value)
+  })
 
 t.create("gets the tagged release's node version version of ionic")
   .get('/v/ionic/next.json')
   .expectJSONTypes(Joi.object({ name: 'node@next' }).unknown())
-  .afterJSON(json => { expectSemverRange(json.value); });
+  .afterJSON(json => {
+    expectSemverRange(json.value)
+  })
 
 t.create('gets the node version of passport from a custom registry')
   .get('/v/passport.json?registry_uri=https://registry.npmjs.com')
   .expectJSONTypes(Joi.object({ name: 'node' }).unknown())
-  .afterJSON(json => { expectSemverRange(json.value); });
+  .afterJSON(json => {
+    expectSemverRange(json.value)
+  })
 
 t.create("gets the tagged release's node version of @cycle/core")
   .get('/v/@cycle/core/canary.json')
   .expectJSONTypes(Joi.object({ name: 'node@canary' }).unknown())
-  .afterJSON(json => { expectSemverRange(json.value); });
+  .afterJSON(json => {
+    expectSemverRange(json.value)
+  })
 
 t.create('invalid package name')
   .get('/v/frodo-is-not-a-package.json')
-  .expectJSON({ name: 'node', value: 'package not found' });
+  .expectJSON({ name: 'node', value: 'package not found' })
diff --git a/services/npm/npm-base.js b/services/npm/npm-base.js
index f6064d6ac13ad2c726eb7be000602f7510387b1a..956978c05d622782d6801cca752d203784d0dc06 100644
--- a/services/npm/npm-base.js
+++ b/services/npm/npm-base.js
@@ -1,12 +1,12 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const { BaseJsonService } = require('../base');
-const { InvalidResponse, NotFound } = require('../errors');
+const Joi = require('joi')
+const { BaseJsonService } = require('../base')
+const { InvalidResponse, NotFound } = require('../errors')
 
 const deprecatedLicenseObjectSchema = Joi.object({
   type: Joi.string().required(),
-});
+})
 const schema = Joi.object({
   devDependencies: Joi.object().pattern(/./, Joi.string()),
   engines: Joi.object().pattern(/./, Joi.string()),
@@ -17,7 +17,7 @@ const schema = Joi.object({
       Joi.alternatives(Joi.string(), deprecatedLicenseObjectSchema)
     )
   ),
-}).required();
+}).required()
 
 // Abstract class for NPM badges which display data about the latest version
 // of a package.
@@ -29,14 +29,14 @@ module.exports = class NpmBase extends BaseJsonService {
         format: '(?:@([^/]+))?/?([^/]*)/?([^/]*)',
         capture: ['scope', 'packageName', 'tag'],
         queryParams: ['registry_uri'],
-      };
+      }
     } else {
       return {
         base,
         format: '(?:@([^/]+)/)?([^/]+)',
         capture: ['scope', 'packageName'],
         queryParams: ['registry_uri'],
-      };
+      }
     }
   }
 
@@ -49,31 +49,31 @@ module.exports = class NpmBase extends BaseJsonService {
       packageName,
       tag,
       registryUrl,
-    };
+    }
   }
 
   static encodeScopedPackage({ scope, packageName }) {
     // e.g. https://registry.npmjs.org/@cedx%2Fgulp-david
-    const encoded = encodeURIComponent(`${scope}/${packageName}`);
-    return `@${encoded}`;
+    const encoded = encodeURIComponent(`${scope}/${packageName}`)
+    return `@${encoded}`
   }
 
   async fetchPackageData({ registryUrl, scope, packageName, tag }) {
-    registryUrl = registryUrl || this.constructor.defaultRegistryUrl;
-    let url;
+    registryUrl = registryUrl || this.constructor.defaultRegistryUrl
+    let url
     if (scope === undefined) {
       // e.g. https://registry.npmjs.org/express/latest
       // Use this endpoint as an optimization. It covers the vast majority of
       // these badges, and the response is smaller.
-      url = `${registryUrl}/${packageName}/latest`;
+      url = `${registryUrl}/${packageName}/latest`
     } else {
       // e.g. https://registry.npmjs.org/@cedx%2Fgulp-david
       // because https://registry.npmjs.org/@cedx%2Fgulp-david/latest does not work
       const scoped = this.constructor.encodeScopedPackage({
         scope,
         packageName,
-      });
-      url = `${registryUrl}/${scoped}`;
+      })
+      url = `${registryUrl}/${scoped}`
     }
     const json = await this._requestJson({
       // We don't validate here because we need to pluck the desired subkey first.
@@ -83,26 +83,26 @@ module.exports = class NpmBase extends BaseJsonService {
       // <https://github.com/npm/npmjs.org/issues/163>
       options: { Accept: '*/*' },
       notFoundMessage: 'package not found',
-    });
+    })
 
-    let packageData;
+    let packageData
     if (scope === undefined) {
-      packageData = json;
+      packageData = json
     } else {
-      const registryTag = tag || 'latest';
-      let latestVersion;
+      const registryTag = tag || 'latest'
+      let latestVersion
       try {
-        latestVersion = json['dist-tags'][registryTag];
+        latestVersion = json['dist-tags'][registryTag]
       } catch (e) {
-        throw new NotFound({ prettyMessage: 'tag not found' });
+        throw new NotFound({ prettyMessage: 'tag not found' })
       }
       try {
-        packageData = json.versions[latestVersion];
+        packageData = json.versions[latestVersion]
       } catch (e) {
-        throw new InvalidResponse('invalid json response');
+        throw new InvalidResponse('invalid json response')
       }
     }
 
-    return this.constructor._validate(packageData, schema);
+    return this.constructor._validate(packageData, schema)
   }
-};
+}
diff --git a/services/npm/npm-downloads.service.js b/services/npm/npm-downloads.service.js
index 3994226fef908b47aa4ec9468756cc3ac01268bd..a8e0be3576dd575e22861c6027c1dea1b994c114 100644
--- a/services/npm/npm-downloads.service.js
+++ b/services/npm/npm-downloads.service.js
@@ -1,8 +1,8 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const { BaseJsonService } = require('../base');
-const { metric } = require('../../lib/text-formatters');
+const Joi = require('joi')
+const { BaseJsonService } = require('../base')
+const { metric } = require('../../lib/text-formatters')
 
 // https://github.com/npm/registry/blob/master/docs/download-counts.md#output
 const pointResponseSchema = Joi.object({
@@ -10,14 +10,14 @@ const pointResponseSchema = Joi.object({
     .integer()
     .min(0)
     .required(),
-}).required();
+}).required()
 
 // https://github.com/npm/registry/blob/master/docs/download-counts.md#output-1
 const rangeResponseSchema = Joi.object({
   downloads: Joi.array()
     .items(pointResponseSchema)
     .required(),
-}).required();
+}).required()
 
 function DownloadsForInterval(interval) {
   const { base, messageSuffix = '', query, isRange = false } = {
@@ -41,15 +41,15 @@ function DownloadsForInterval(interval) {
       query: 'range/1000-01-01:3000-01-01',
       isRange: true,
     },
-  }[interval];
+  }[interval]
 
-  const schema = isRange ? rangeResponseSchema : pointResponseSchema;
+  const schema = isRange ? rangeResponseSchema : pointResponseSchema
 
   // This hits an entirely different API from the rest of the NPM services, so
   // it does not use NpmBase.
   return class NpmDownloads extends BaseJsonService {
     static get category() {
-      return 'downloads';
+      return 'downloads'
     }
 
     static get url() {
@@ -57,7 +57,7 @@ function DownloadsForInterval(interval) {
         base,
         format: '(.*)',
         capture: ['packageName'],
-      };
+      }
     }
 
     static get examples() {
@@ -67,14 +67,14 @@ function DownloadsForInterval(interval) {
           previewUrl: 'localeval',
           keywords: ['node'],
         },
-      ];
+      ]
     }
 
     static render({ downloads }) {
       return {
         message: `${metric(downloads)}${messageSuffix}`,
         color: downloads > 0 ? 'brightgreen' : 'red',
-      };
+      }
     }
 
     async handle({ packageName }) {
@@ -82,15 +82,15 @@ function DownloadsForInterval(interval) {
         schema,
         url: `https://api.npmjs.org/downloads/${query}/${packageName}`,
         notFoundMessage: 'project not found',
-      });
+      })
       if (isRange) {
         downloads = downloads
           .map(item => item.downloads)
-          .reduce((accum, current) => accum + current);
+          .reduce((accum, current) => accum + current)
       }
-      return this.constructor.render({ downloads });
+      return this.constructor.render({ downloads })
     }
-  };
+  }
 }
 
-module.exports = ['week', 'month', 'year', 'total'].map(DownloadsForInterval);
+module.exports = ['week', 'month', 'year', 'total'].map(DownloadsForInterval)
diff --git a/services/npm/npm-license.service.js b/services/npm/npm-license.service.js
index cc4afb61d065275475a27fd2f03844071cc214dc..a77bfa9db56d242234b3210ffc143e60d023fa6f 100644
--- a/services/npm/npm-license.service.js
+++ b/services/npm/npm-license.service.js
@@ -1,20 +1,20 @@
-'use strict';
+'use strict'
 
-const { licenseToColor } = require('../../lib/licenses');
-const { toArray } = require('../../lib/badge-data');
-const NpmBase = require('./npm-base');
+const { licenseToColor } = require('../../lib/licenses')
+const { toArray } = require('../../lib/badge-data')
+const NpmBase = require('./npm-base')
 
 module.exports = class NpmLicense extends NpmBase {
   static get category() {
-    return 'license';
+    return 'license'
   }
 
   static get defaultBadgeData() {
-    return { label: 'license' };
+    return { label: 'license' }
   }
 
   static get url() {
-    return this.buildUrl('npm/l', { withTag: false });
+    return this.buildUrl('npm/l', { withTag: false })
   }
 
   static get examples() {
@@ -28,12 +28,12 @@ module.exports = class NpmLicense extends NpmBase {
         query: { registry_uri: 'https://registry.npmjs.com' },
         keywords: ['node'],
       },
-    ];
+    ]
   }
 
   static render({ licenses }) {
     if (licenses.length === 0) {
-      return { message: 'missing', color: 'red' };
+      return { message: 'missing', color: 'red' }
     }
 
     return {
@@ -41,22 +41,22 @@ module.exports = class NpmLicense extends NpmBase {
       // TODO This does not provide a color when more than one license is
       // present. Probably that should be fixed.
       color: licenseToColor(licenses),
-    };
+    }
   }
 
   async handle(namedParams, queryParams) {
     const { scope, packageName, registryUrl } = this.constructor.unpackParams(
       namedParams,
       queryParams
-    );
+    )
     const { license } = await this.fetchPackageData({
       scope,
       packageName,
       registryUrl,
-    });
+    })
     const licenses = toArray(license).map(
       license => (typeof license === 'string' ? license : license.type)
-    );
-    return this.constructor.render({ licenses });
+    )
+    return this.constructor.render({ licenses })
   }
-};
+}
diff --git a/services/npm/npm-type-definitions.service.js b/services/npm/npm-type-definitions.service.js
index cc21baab178763cbb7f9c7daf6799b5806ddc5f4..31028dfea024f24002dde703eed9ad38ce40cd16 100644
--- a/services/npm/npm-type-definitions.service.js
+++ b/services/npm/npm-type-definitions.service.js
@@ -1,19 +1,19 @@
-'use strict';
+'use strict'
 
-const { rangeStart, minor } = require('../../lib/version');
-const NpmBase = require('./npm-base');
+const { rangeStart, minor } = require('../../lib/version')
+const NpmBase = require('./npm-base')
 
 module.exports = class NpmTypeDefinitions extends NpmBase {
   static get category() {
-    return 'version';
+    return 'version'
   }
 
   static get defaultBadgeData() {
-    return { label: 'type definitions' };
+    return { label: 'type definitions' }
   }
 
   static get url() {
-    return this.buildUrl('npm/types', { withTag: false });
+    return this.buildUrl('npm/types', { withTag: false })
   }
 
   static get examples() {
@@ -23,7 +23,7 @@ module.exports = class NpmTypeDefinitions extends NpmBase {
         previewUrl: 'chalk',
         keywords: ['node', 'typescript', 'flow'],
       },
-    ];
+    ]
   }
 
   static transform({ devDependencies }) {
@@ -32,12 +32,12 @@ module.exports = class NpmTypeDefinitions extends NpmBase {
         { language: 'TypeScript', range: devDependencies.typescript },
         { language: 'Flow', range: devDependencies['flow-bin'] },
       ].filter(({ range }) => range !== undefined),
-    };
+    }
   }
 
   static render({ supportedLanguages }) {
     if (supportedLanguages.length === 0) {
-      return { message: 'none', color: 'lightgray' };
+      return { message: 'none', color: 'lightgray' }
     } else {
       return {
         message: supportedLanguages
@@ -46,7 +46,7 @@ module.exports = class NpmTypeDefinitions extends NpmBase {
           )
           .join(' | '),
         color: 'blue',
-      };
+      }
     }
   }
 
@@ -54,13 +54,13 @@ module.exports = class NpmTypeDefinitions extends NpmBase {
     const { scope, packageName, registryUrl } = this.constructor.unpackParams(
       namedParams,
       queryParams
-    );
+    )
     const json = await this.fetchPackageData({
       scope,
       packageName,
       registryUrl,
-    });
-    const props = this.constructor.transform(json);
-    return this.constructor.render(props);
+    })
+    const props = this.constructor.transform(json)
+    return this.constructor.render(props)
   }
-};
+}
diff --git a/services/npm/npm-type-definitions.spec.js b/services/npm/npm-type-definitions.spec.js
index d4d21aa5ace2bd238076b1ade2b215c175d6d083..c14068cda6e696b6d426f881bef07fe013d6592b 100644
--- a/services/npm/npm-type-definitions.spec.js
+++ b/services/npm/npm-type-definitions.spec.js
@@ -1,16 +1,16 @@
-'use strict';
+'use strict'
 
-const { test, given } = require('sazerac');
-const NpmTypeDefinitions = require('./npm-type-definitions.service');
+const { test, given } = require('sazerac')
+const NpmTypeDefinitions = require('./npm-type-definitions.service')
 
 const transformAndRender = json =>
-  NpmTypeDefinitions.render(NpmTypeDefinitions.transform(json));
+  NpmTypeDefinitions.render(NpmTypeDefinitions.transform(json))
 
 describe('NPM type definitions badge', function() {
   test(transformAndRender, () => {
     given({ devDependencies: { typescript: '^2.4.7' } }).expect({
       message: 'TypeScript v2.4',
       color: 'blue',
-    });
-  });
-});
+    })
+  })
+})
diff --git a/services/npm/npm-version.service.js b/services/npm/npm-version.service.js
index bf16e83abc8789165df697532afa345e2d7399d7..97634705b6e9ddd17747a42237e6467e7069c67a 100644
--- a/services/npm/npm-version.service.js
+++ b/services/npm/npm-version.service.js
@@ -1,27 +1,27 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const { addv } = require('../../lib/text-formatters');
-const { version: versionColor } = require('../../lib/color-formatters');
-const { NotFound } = require('../errors');
-const NpmBase = require('./npm-base');
+const Joi = require('joi')
+const { addv } = require('../../lib/text-formatters')
+const { version: versionColor } = require('../../lib/color-formatters')
+const { NotFound } = require('../errors')
+const NpmBase = require('./npm-base')
 
 // Joi.string should be a semver.
 const schema = Joi.object()
   .pattern(/./, Joi.string())
-  .required();
+  .required()
 
 module.exports = class NpmVersion extends NpmBase {
   static get category() {
-    return 'version';
+    return 'version'
   }
 
   static get url() {
-    return this.buildUrl('npm/v', { withTag: true });
+    return this.buildUrl('npm/v', { withTag: true })
   }
 
   static get defaultBadgeData() {
-    return { label: 'npm' };
+    return { label: 'npm' }
   }
 
   static get examples() {
@@ -51,7 +51,7 @@ module.exports = class NpmVersion extends NpmBase {
         previewUrl: '@cycle/core/canary',
         keywords: ['node'],
       },
-    ];
+    ]
   }
 
   static render({ tag, version }) {
@@ -59,7 +59,7 @@ module.exports = class NpmVersion extends NpmBase {
       label: tag ? `npm@${tag}` : undefined,
       message: addv(version),
       color: versionColor(version),
-    };
+    }
   }
 
   async handle(namedParams, queryParams) {
@@ -68,26 +68,26 @@ module.exports = class NpmVersion extends NpmBase {
       packageName,
       tag,
       registryUrl,
-    } = this.constructor.unpackParams(namedParams, queryParams);
+    } = this.constructor.unpackParams(namedParams, queryParams)
 
     const slug =
       scope === undefined
         ? packageName
-        : this.constructor.encodeScopedPackage({ scope, packageName });
+        : this.constructor.encodeScopedPackage({ scope, packageName })
 
     const packageData = await this._requestJson({
       schema,
       url: `${registryUrl}/-/package/${slug}/dist-tags`,
       notFoundMessage: 'package not found',
-    });
+    })
 
     if (tag && !(tag in packageData)) {
-      throw new NotFound({ prettyMessage: 'tag not found' });
+      throw new NotFound({ prettyMessage: 'tag not found' })
     }
 
     return this.constructor.render({
       tag,
       version: packageData[tag || 'latest'],
-    });
+    })
   }
-};
+}
diff --git a/services/npm/npm.tester.js b/services/npm/npm.tester.js
index 486ed22e0fbcf5e796a5d3fc44bd74a9abc33d0d..6f8347b201e31599b9f5c2e15ad846aef24a0845 100644
--- a/services/npm/npm.tester.js
+++ b/services/npm/npm.tester.js
@@ -1,173 +1,221 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isMetric, isSemver } = require('../test-validators');
-const colorscheme = require('../../lib/colorscheme.json');
-const mapValues = require('lodash.mapvalues');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isMetric, isSemver } = require('../test-validators')
+const colorscheme = require('../../lib/colorscheme.json')
+const mapValues = require('lodash.mapvalues')
 
-const t = new ServiceTester({ id: 'npm', title: 'NPM' });
-module.exports = t;
-const colorsB = mapValues(colorscheme, 'colorB');
+const t = new ServiceTester({ id: 'npm', title: 'NPM' })
+module.exports = t
+const colorsB = mapValues(colorscheme, 'colorB')
 
-const isTypeDefinition = Joi.string().regex(/^(Flow|TypeScript) v?[0-9]+.[0-9]+( \| (Flow|TypeScript) v?[0-9]+.[0-9]+)?$/);
+const isTypeDefinition = Joi.string().regex(
+  /^(Flow|TypeScript) v?[0-9]+.[0-9]+( \| (Flow|TypeScript) v?[0-9]+.[0-9]+)?$/
+)
 
 t.create('total downloads of left-pad')
   .get('/dt/left-pad.json?style=_shields_test')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric, colorB: colorsB.brightgreen }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+      colorB: colorsB.brightgreen,
+    })
+  )
 
 t.create('total downloads of @cycle/core')
   .get('/dt/@cycle/core.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }));
+  .expectJSONTypes(Joi.object().keys({ name: 'downloads', value: isMetric }))
 
 t.create('total downloads of package with zero downloads')
   .get('/dt/package-no-downloads.json?style=_shields_test')
-  .intercept(nock => nock('https://api.npmjs.org')
-    .get('/downloads/range/1000-01-01:3000-01-01/package-no-downloads')
-    .reply(200, {
-      downloads: [
-        { downloads: 0, day: '2018-01-01' }
-      ],
-    }))
-  .expectJSON({ name: 'downloads', value: '0', colorB: colorsB.red });
+  .intercept(nock =>
+    nock('https://api.npmjs.org')
+      .get('/downloads/range/1000-01-01:3000-01-01/package-no-downloads')
+      .reply(200, {
+        downloads: [{ downloads: 0, day: '2018-01-01' }],
+      })
+  )
+  .expectJSON({ name: 'downloads', value: '0', colorB: colorsB.red })
 
 t.create('exact total downloads value')
   .get('/dt/exact-value.json')
-  .intercept(nock => nock('https://api.npmjs.org')
-    .get('/downloads/range/1000-01-01:3000-01-01/exact-value')
-    .reply(200, {
-      downloads: [
-        { downloads: 2, day: '2018-01-01' },
-        { downloads: 3, day: '2018-01-02' },
-      ],
-    }))
-  .expectJSON({ name: 'downloads', value: '5' });
+  .intercept(nock =>
+    nock('https://api.npmjs.org')
+      .get('/downloads/range/1000-01-01:3000-01-01/exact-value')
+      .reply(200, {
+        downloads: [
+          { downloads: 2, day: '2018-01-01' },
+          { downloads: 3, day: '2018-01-02' },
+        ],
+      })
+  )
+  .expectJSON({ name: 'downloads', value: '5' })
 
 t.create('total downloads when network is off')
   .get('/dt/@cycle/core.json?style=_shields_test')
   .networkOff()
-  .expectJSON({  name: 'downloads', value: 'inaccessible' , colorB: colorsB.lightgray });
+  .expectJSON({
+    name: 'downloads',
+    value: 'inaccessible',
+    colorB: colorsB.lightgray,
+  })
 
 t.create('total downloads of unknown package')
   .get('/dt/npm-api-does-not-have-this-package.json?style=_shields_test')
-  .expectJSON({  name: 'downloads', value: 'project not found' , colorB: colorsB.red });
+  .expectJSON({
+    name: 'downloads',
+    value: 'project not found',
+    colorB: colorsB.red,
+  })
 
 t.create('gets the package version of left-pad')
   .get('/v/left-pad.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'npm', value: isSemver }));
+  .expectJSONTypes(Joi.object().keys({ name: 'npm', value: isSemver }))
 
 t.create('gets the package version of @cycle/core')
   .get('/v/@cycle/core.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'npm', value: isSemver }));
+  .expectJSONTypes(Joi.object().keys({ name: 'npm', value: isSemver }))
 
 t.create('gets a tagged package version of npm')
   .get('/v/npm/next.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'npm@next', value: isSemver }));
+  .expectJSONTypes(Joi.object().keys({ name: 'npm@next', value: isSemver }))
 
 t.create('gets the correct tagged package version of npm')
-  .intercept(nock => nock('https://registry.npmjs.org')
-    .get('/-/package/npm/dist-tags')
-    .reply(200, { latest: "1.2.3", next: "4.5.6" }))
+  .intercept(nock =>
+    nock('https://registry.npmjs.org')
+      .get('/-/package/npm/dist-tags')
+      .reply(200, { latest: '1.2.3', next: '4.5.6' })
+  )
   .get('/v/npm/next.json')
-  .expectJSON({ name: 'npm@next', value: 'v4.5.6' });
+  .expectJSON({ name: 'npm@next', value: 'v4.5.6' })
 
 t.create('returns an error for version with an invalid tag')
   .get('/v/npm/frodo.json')
-  .expectJSON({ name: 'npm', value: 'tag not found' });
+  .expectJSON({ name: 'npm', value: 'tag not found' })
 
 t.create('gets the package version of left-pad from a custom registry')
   .get('/v/left-pad.json?registry_uri=https://registry.npmjs.com')
-  .expectJSONTypes(Joi.object().keys({ name: 'npm', value: isSemver }));
+  .expectJSONTypes(Joi.object().keys({ name: 'npm', value: isSemver }))
 
 t.create('gets the tagged package version of @cycle/core')
   .get('/v/@cycle/core/canary.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'npm@canary', value: isSemver }));
+  .expectJSONTypes(Joi.object().keys({ name: 'npm@canary', value: isSemver }))
 
-t.create('gets the tagged package version of @cycle/core from a custom registry')
+t.create(
+  'gets the tagged package version of @cycle/core from a custom registry'
+)
   .get('/v/@cycle/core/canary.json?registry_uri=https://registry.npmjs.com')
-  .expectJSONTypes(Joi.object().keys({ name: 'npm@canary', value: isSemver }));
+  .expectJSONTypes(Joi.object().keys({ name: 'npm@canary', value: isSemver }))
 
 t.create('gets the license of express')
   .get('/l/express.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'license', value: 'MIT' }));
+  .expectJSONTypes(Joi.object().keys({ name: 'license', value: 'MIT' }))
 
 t.create('gets the license of express from a custom registry')
   .get('/l/express.json?registry_uri=https://registry.npmjs.com')
-  .expectJSONTypes(Joi.object().keys({ name: 'license', value: 'MIT' }));
+  .expectJSONTypes(Joi.object().keys({ name: 'license', value: 'MIT' }))
 
 t.create('invalid package name')
   .get('/v/frodo-is-not-a-package.json')
-  .expectJSON({ name: 'npm', value: 'package not found' });
+  .expectJSON({ name: 'npm', value: 'package not found' })
 
 t.create('gets the package version of left-pad from a custom registry')
   .get('/v/left-pad.json?registry_uri=https://registry.npmjs.com')
-  .expectJSONTypes(Joi.object().keys({ name: 'npm', value: isSemver }));
+  .expectJSONTypes(Joi.object().keys({ name: 'npm', value: isSemver }))
 
 t.create('public domain license')
   .get('/l/redux-auth.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'WTFPL', colorB: '#7cd958' });
+  .expectJSON({ name: 'license', value: 'WTFPL', colorB: '#7cd958' })
 
 t.create('copyleft license')
   .get('/l/trianglify.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'GPL-3.0', colorB: colorsB.orange });
+  .expectJSON({ name: 'license', value: 'GPL-3.0', colorB: colorsB.orange })
 
 t.create('permissive license')
   .get('/l/express.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'MIT', colorB: colorsB.green });
+  .expectJSON({ name: 'license', value: 'MIT', colorB: colorsB.green })
 
 t.create('permissive license for scoped package')
   .get('/l/@cycle%2Fcore.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'MIT', colorB: colorsB.green });
+  .expectJSON({ name: 'license', value: 'MIT', colorB: colorsB.green })
 
-t.create('permissive and copyleft licenses (SPDX license expression syntax version 2.0)')
+t.create(
+  'permissive and copyleft licenses (SPDX license expression syntax version 2.0)'
+)
   .get('/l/rho-cc-promise.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: '(MPL-2.0 OR MIT)', colorB: colorsB.lightgrey });
+  .expectJSON({
+    name: 'license',
+    value: '(MPL-2.0 OR MIT)',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('license for package without a license property')
   .get('/l/package-without-license.json?style=_shields_test')
-  .intercept(nock => nock('https://registry.npmjs.org')
-    .get('/package-without-license/latest')
-    .reply(200, {
-      name: 'package-without-license'
-    }))
-  .expectJSON({ name: 'license', value: 'missing', colorB: colorsB.red });
+  .intercept(nock =>
+    nock('https://registry.npmjs.org')
+      .get('/package-without-license/latest')
+      .reply(200, {
+        name: 'package-without-license',
+      })
+  )
+  .expectJSON({ name: 'license', value: 'missing', colorB: colorsB.red })
 
 t.create('license for package with a license object')
   .get('/l/package-license-object.json?style=_shields_test')
-  .intercept(nock => nock('https://registry.npmjs.org')
-    .get('/package-license-object/latest')
-    .reply(200, {
-      name: 'package-license-object',
-      license: {
-        type: 'MIT',
-        url: 'https://www.opensource.org/licenses/mit-license.php'
-      }
-    }))
-  .expectJSON({ name: 'license', value: 'MIT', colorB: colorsB.green });
+  .intercept(nock =>
+    nock('https://registry.npmjs.org')
+      .get('/package-license-object/latest')
+      .reply(200, {
+        name: 'package-license-object',
+        license: {
+          type: 'MIT',
+          url: 'https://www.opensource.org/licenses/mit-license.php',
+        },
+      })
+  )
+  .expectJSON({ name: 'license', value: 'MIT', colorB: colorsB.green })
 
 t.create('license for package with a license array')
   .get('/l/package-license-array.json?style=_shields_test')
-  .intercept(nock => nock('https://registry.npmjs.org')
-    .get('/package-license-array/latest')
-    .reply(200, {
-      name: 'package-license-object',
-      license: ['MPL-2.0', 'MIT']
-    }))
-  .expectJSON({ name: 'license', value: 'MPL-2.0, MIT', colorB: colorsB.lightgrey });
+  .intercept(nock =>
+    nock('https://registry.npmjs.org')
+      .get('/package-license-array/latest')
+      .reply(200, {
+        name: 'package-license-object',
+        license: ['MPL-2.0', 'MIT'],
+      })
+  )
+  .expectJSON({
+    name: 'license',
+    value: 'MPL-2.0, MIT',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('license for unknown package')
   .get('/l/npm-registry-does-not-have-this-package.json?style=_shields_test')
-  .expectJSON({ name: 'license', value: 'package not found', colorB: colorsB.red });
+  .expectJSON({
+    name: 'license',
+    value: 'package not found',
+    colorB: colorsB.red,
+  })
 
 t.create('license when network is off')
   .get('/l/pakage-network-off.json?style=_shields_test')
   .networkOff()
-  .expectJSON({ name: 'license', value: 'inaccessible', colorB: colorsB.lightgrey });
+  .expectJSON({
+    name: 'license',
+    value: 'inaccessible',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('types')
   .get('/types/chalk.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'type definitions', value: isTypeDefinition }));
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'type definitions', value: isTypeDefinition })
+  )
 
 t.create('no types')
   .get('/types/left-pad.json')
-  .expectJSON({ name: 'type definitions', value: 'none' });
+  .expectJSON({ name: 'type definitions', value: 'none' })
diff --git a/services/nsp/nsp.tester.js b/services/nsp/nsp.tester.js
index e409cb60b264dcc304b218045c108504c583f2df..82469364b74d6190eee3593eb715c0474681923f 100644
--- a/services/nsp/nsp.tester.js
+++ b/services/nsp/nsp.tester.js
@@ -3,32 +3,32 @@
 const Joi = require('joi')
 const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({id: 'nsp', title: 'Node Security Platform'})
+const t = new ServiceTester({ id: 'nsp', title: 'Node Security Platform' })
 
 const formats = {
   A: '/nsp/npm/:package.:format',
   B: '/nsp/npm/:package/:version.:format',
   C: '/nsp/npm/@:scope/:package.:format',
-  D: '/nsp/npm/@:scope/:package/:version.:format'
+  D: '/nsp/npm/@:scope/:package/:version.:format',
 }
 
 const noExistPackages = {
   A: '/npm/some-no-exist.json',
   B: '/npm/some-no-exist/1.0.0.json',
   C: '/npm/@some-no-exist/some-no-exist.json',
-  D: '/npm/@some-no-exist/some-no-exist/1.0.0.json'
+  D: '/npm/@some-no-exist/some-no-exist/1.0.0.json',
 }
 
 const withoutVulnerabilities = {
   A: '/npm/bronze.json',
   B: '/npm/bronze/1.4.0.json',
   C: '/npm/@cycle/core.json',
-  D: '/npm/@cycle/core/1.0.0.json'
+  D: '/npm/@cycle/core/1.0.0.json',
 }
 
 const withVulnerabilities = {
   A: '/npm/nodeaaaaa.json',
-  B: '/npm/express/1.0.0.json'
+  B: '/npm/express/1.0.0.json',
 }
 
 Object.keys(formats).forEach(format => {
@@ -39,19 +39,24 @@ Object.keys(formats).forEach(format => {
   if (typeof noExist === 'string') {
     t.create(`Format '${formats[format]}' where it doesn't exist`)
       .get(noExist)
-      .expectJSON({name: 'nsp', value: 'no known vulnerabilities'})
+      .expectJSON({ name: 'nsp', value: 'no known vulnerabilities' })
   }
 
   if (typeof withVulnerability === 'string') {
     t.create(`Format '${formats[format]}' with vulnerabilities`)
       .get(withVulnerability)
-      .expectJSONTypes(Joi.object().keys({name: 'nsp', value: Joi.string().regex(/^[0-9]+ vulnerabilities$/)}))
+      .expectJSONTypes(
+        Joi.object().keys({
+          name: 'nsp',
+          value: Joi.string().regex(/^[0-9]+ vulnerabilities$/),
+        })
+      )
   }
 
   if (typeof withoutVulnerability === 'string') {
     t.create(`Format '${formats[format]}' without vulnerabilities`)
       .get(withoutVulnerability)
-      .expectJSON({name: 'nsp', value: 'no known vulnerabilities'})
+      .expectJSON({ name: 'nsp', value: 'no known vulnerabilities' })
   }
 })
 
diff --git a/services/nuget-fixtures.js b/services/nuget-fixtures.js
index ea7486b21d1b38582d5770cb8a374a6a84cf2c36..a5c5e1acb5cc0dfd603b12c15914d7d2e8768945 100644
--- a/services/nuget-fixtures.js
+++ b/services/nuget-fixtures.js
@@ -1,60 +1,51 @@
-'use strict';
+'use strict'
 
 const queryIndex = JSON.stringify({
-  "resources": [
-    { "@id": "https://api-v2v3search-0.nuget.org/query", "@type": "SearchQueryService" }
-  ]
-});
+  resources: [
+    {
+      '@id': 'https://api-v2v3search-0.nuget.org/query',
+      '@type': 'SearchQueryService',
+    },
+  ],
+})
 
 const nuGetV2VersionJsonWithDash = JSON.stringify({
   d: {
-    results: [
-      { NormalizedVersion: '1.2-beta' }
-    ]
-  }
-});
+    results: [{ NormalizedVersion: '1.2-beta' }],
+  },
+})
 const nuGetV2VersionJsonFirstCharZero = JSON.stringify({
   d: {
-    results: [
-      { NormalizedVersion: '0.35' }
-    ]
-  }
-});
+    results: [{ NormalizedVersion: '0.35' }],
+  },
+})
 const nuGetV2VersionJsonFirstCharNotZero = JSON.stringify({
   d: {
-    results: [
-      { NormalizedVersion: '1.2.7' }
-    ]
-  }
-});
+    results: [{ NormalizedVersion: '1.2.7' }],
+  },
+})
 
 const nuGetV3VersionJsonWithDash = JSON.stringify({
   data: [
     {
-      versions: [
-        { version: '1.2-beta' }
-      ]
-    }
-  ]
-});
+      versions: [{ version: '1.2-beta' }],
+    },
+  ],
+})
 const nuGetV3VersionJsonFirstCharZero = JSON.stringify({
   data: [
     {
-      versions: [
-        { version: '0.35' }
-      ]
-    }
-  ]
-});
+      versions: [{ version: '0.35' }],
+    },
+  ],
+})
 const nuGetV3VersionJsonFirstCharNotZero = JSON.stringify({
   data: [
     {
-      versions: [
-        { version: '1.2.7' }
-      ]
-    }
-  ]
-});
+      versions: [{ version: '1.2.7' }],
+    },
+  ],
+})
 
 module.exports = {
   queryIndex,
@@ -64,4 +55,4 @@ module.exports = {
   nuGetV3VersionJsonWithDash,
   nuGetV3VersionJsonFirstCharZero,
   nuGetV3VersionJsonFirstCharNotZero,
-};
+}
diff --git a/services/nuget/nuget.tester.js b/services/nuget/nuget.tester.js
index 541d353a8a096b6d271d9e72250f3d7aea91cabc..19cf4f799ed74e3c5fb8bc0429ae5eedf32b5071 100644
--- a/services/nuget/nuget.tester.js
+++ b/services/nuget/nuget.tester.js
@@ -1,233 +1,257 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isMetric,
   isVPlusDottedVersionNClauses,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators');
-const colorscheme = require('../../lib/colorscheme.json');
+} = require('../test-validators')
+const colorscheme = require('../../lib/colorscheme.json')
 const {
   queryIndex,
   nuGetV3VersionJsonWithDash,
   nuGetV3VersionJsonFirstCharZero,
   nuGetV3VersionJsonFirstCharNotZero,
-} = require('../nuget-fixtures');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'nuget', title: 'NuGet' });
-module.exports = t;
+} = require('../nuget-fixtures')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'nuget', title: 'NuGet' })
+module.exports = t
 
 // downloads
 
 t.create('total downloads (valid)')
   .get('/dt/Microsoft.AspNetCore.Mvc.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('total downloads (not found)')
   .get('/dt/not-a-real-package.json')
-  .expectJSON({name: 'downloads', value: 'not found'});
+  .expectJSON({ name: 'downloads', value: 'not found' })
 
 t.create('total downloads (connection error)')
   .get('/dt/Microsoft.AspNetCore.Mvc.json')
   .networkOff()
-  .expectJSON({name: 'downloads', value: 'inaccessible'});
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 t.create('total downloads (unexpected first response)')
   .get('/dt/Microsoft.AspNetCore.Mvc.json')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'downloads', value: 'invalid'});
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('total downloads (unexpected second response)')
   .get('/dt/Microsoft.AspNetCore.Mvc.json')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'downloads', value: 'invalid'});
-
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 // version
 
 t.create('version (valid)')
   .get('/v/Microsoft.AspNetCore.Mvc.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'nuget',
-    value: isVPlusDottedVersionNClauses,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'nuget',
+      value: isVPlusDottedVersionNClauses,
+    })
+  )
 
 t.create('version (mocked, yellow badge)')
   .get('/v/Microsoft.AspNetCore.Mvc.json?style=_shields_test')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true")
-    .reply(200, nuGetV3VersionJsonWithDash)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true')
+      .reply(200, nuGetV3VersionJsonWithDash)
   )
   .expectJSON({
     name: 'nuget',
     value: 'v1.2-beta',
-    colorB: colorscheme.yellow.colorB
-  });
+    colorB: colorscheme.yellow.colorB,
+  })
 
 t.create('version (mocked, orange badge)')
   .get('/v/Microsoft.AspNetCore.Mvc.json?style=_shields_test')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true")
-    .reply(200, nuGetV3VersionJsonFirstCharZero)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true')
+      .reply(200, nuGetV3VersionJsonFirstCharZero)
   )
   .expectJSON({
     name: 'nuget',
     value: 'v0.35',
-    colorB: colorscheme.orange.colorB
-  });
+    colorB: colorscheme.orange.colorB,
+  })
 
 t.create('version (mocked, blue badge)')
   .get('/v/Microsoft.AspNetCore.Mvc.json?style=_shields_test')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true")
-    .reply(200, nuGetV3VersionJsonFirstCharNotZero)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true')
+      .reply(200, nuGetV3VersionJsonFirstCharNotZero)
   )
   .expectJSON({
     name: 'nuget',
     value: 'v1.2.7',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('version (not found)')
   .get('/v/not-a-real-package.json')
-  .expectJSON({name: 'nuget', value: 'not found'});
+  .expectJSON({ name: 'nuget', value: 'not found' })
 
 t.create('version (connection error)')
   .get('/v/Microsoft.AspNetCore.Mvc.json')
   .networkOff()
-  .expectJSON({name: 'nuget', value: 'inaccessible'});
+  .expectJSON({ name: 'nuget', value: 'inaccessible' })
 
 t.create('version (unexpected first response)')
   .get('/v/Microsoft.AspNetCore.Mvc.json')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'nuget', value: 'invalid'});
+  .expectJSON({ name: 'nuget', value: 'invalid' })
 
 t.create('version (unexpected second response)')
   .get('/v/Microsoft.AspNetCore.Mvc.json')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'nuget', value: 'invalid'});
-
+  .expectJSON({ name: 'nuget', value: 'invalid' })
 
 // version (pre)
 
 t.create('version (pre) (valid)')
   .get('/vpre/Microsoft.AspNetCore.Mvc.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'nuget',
-    value: isVPlusDottedVersionNClausesWithOptionalSuffix,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'nuget',
+      value: isVPlusDottedVersionNClausesWithOptionalSuffix,
+    })
+  )
 
-  t.create('version (pre) (mocked, yellow badge)')
+t.create('version (pre) (mocked, yellow badge)')
   .get('/vpre/Microsoft.AspNetCore.Mvc.json?style=_shields_test')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true")
-    .reply(200, nuGetV3VersionJsonWithDash)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true')
+      .reply(200, nuGetV3VersionJsonWithDash)
   )
   .expectJSON({
     name: 'nuget',
     value: 'v1.2-beta',
-    colorB: colorscheme.yellow.colorB
-  });
+    colorB: colorscheme.yellow.colorB,
+  })
 
 t.create('version (pre) (mocked, orange badge)')
   .get('/vpre/Microsoft.AspNetCore.Mvc.json?style=_shields_test')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true")
-    .reply(200, nuGetV3VersionJsonFirstCharZero)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true')
+      .reply(200, nuGetV3VersionJsonFirstCharZero)
   )
   .expectJSON({
     name: 'nuget',
     value: 'v0.35',
-    colorB: colorscheme.orange.colorB
-  });
+    colorB: colorscheme.orange.colorB,
+  })
 
 t.create('version (pre) (mocked, blue badge)')
   .get('/vpre/Microsoft.AspNetCore.Mvc.json?style=_shields_test')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true")
-    .reply(200, nuGetV3VersionJsonFirstCharNotZero)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true')
+      .reply(200, nuGetV3VersionJsonFirstCharNotZero)
   )
   .expectJSON({
     name: 'nuget',
     value: 'v1.2.7',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('version (pre) (not found)')
   .get('/vpre/not-a-real-package.json')
-  .expectJSON({name: 'nuget', value: 'not found'});
+  .expectJSON({ name: 'nuget', value: 'not found' })
 
 t.create('version (pre) (connection error)')
   .get('/vpre/Microsoft.AspNetCore.Mvc.json')
   .networkOff()
-  .expectJSON({name: 'nuget', value: 'inaccessible'});
+  .expectJSON({ name: 'nuget', value: 'inaccessible' })
 
 t.create('version (pre) (unexpected first response)')
   .get('/vpre/Microsoft.AspNetCore.Mvc.json')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'nuget', value: 'invalid'});
+  .expectJSON({ name: 'nuget', value: 'invalid' })
 
 t.create('version (pre) (unexpected second response)')
   .get('/vpre/Microsoft.AspNetCore.Mvc.json')
-  .intercept(nock => nock('https://api.nuget.org')
-    .get("/v3/index.json")
-    .reply(200, queryIndex)
+  .intercept(nock =>
+    nock('https://api.nuget.org')
+      .get('/v3/index.json')
+      .reply(200, queryIndex)
   )
-  .intercept(nock => nock('https://api-v2v3search-0.nuget.org')
-    .get("/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api-v2v3search-0.nuget.org')
+      .get('/query?q=packageid:microsoft.aspnetcore.mvc&prerelease=true')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'nuget', value: 'invalid'});
+  .expectJSON({ name: 'nuget', value: 'invalid' })
diff --git a/services/packagist/packagist.tester.js b/services/packagist/packagist.tester.js
index f0a01eaca81c2feabc7d787f7da80cba3b9f311c..01f0f04e9d262808c62ec5b3a462eee7a3fe772c 100644
--- a/services/packagist/packagist.tester.js
+++ b/services/packagist/packagist.tester.js
@@ -1,12 +1,12 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isComposerVersion,
   isMetric,
-  isMetricOverTimePeriod
-} = require('../test-validators');
+  isMetricOverTimePeriod,
+} = require('../test-validators')
 
 /*
   validator for a packagist version number
@@ -15,104 +15,109 @@ const {
   "version names should match 'X.Y.Z', or 'vX.Y.Z',
   with an optional suffix for RC, beta, alpha or patch versions"
 */
-const isPackagistVersion = Joi.string().regex(/^v?[0-9]+.[0-9]+.[0-9]+[\S]*$/);
-
-const t = new ServiceTester({ id: 'packagist', title: 'PHP version from Packagist' });
-module.exports = t;
+const isPackagistVersion = Joi.string().regex(/^v?[0-9]+.[0-9]+.[0-9]+[\S]*$/)
 
+const t = new ServiceTester({
+  id: 'packagist',
+  title: 'PHP version from Packagist',
+})
+module.exports = t
 
 // tests for php version support endpoint
 
 t.create('gets the package version of symfony')
   .get('/php-v/symfony/symfony.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'PHP', value: isComposerVersion }));
+  .expectJSONTypes(Joi.object().keys({ name: 'PHP', value: isComposerVersion }))
 
 t.create('gets the package version of symfony 2.8')
   .get('/php-v/symfony/symfony/v2.8.0.json')
-  .expectJSONTypes(Joi.object().keys({ name: 'PHP', value: isComposerVersion }));
+  .expectJSONTypes(Joi.object().keys({ name: 'PHP', value: isComposerVersion }))
 
 t.create('invalid package name')
   .get('/php-v/frodo/is-not-a-package.json')
-  .expectJSON({ name: 'PHP', value: 'invalid' });
-
+  .expectJSON({ name: 'PHP', value: 'invalid' })
 
 // tests for download stats endpoints
 
 t.create('daily downloads (valid, no package version specified)')
   .get('/dd/doctrine/orm.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriod
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriod,
+    })
+  )
 
 t.create('monthly downloads (valid, no package version specified)')
   .get('/dm/doctrine/orm.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriod
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriod,
+    })
+  )
 
 t.create('total downloads (valid, no package version specified)')
   .get('/dt/doctrine/orm.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric
-  }));
-
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 // note: packagist can't give us download stats for a specific version
 t.create('daily downloads (invalid, package version specified)')
   .get('/dd/symfony/symfony/v2.8.0.json')
-  .expectJSON({ name: 'downloads', value: 'invalid' });
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('monthly downloads (invalid, package version in request)')
   .get('/dm/symfony/symfony/v2.8.0.json')
-  .expectJSON({ name: 'downloads', value: 'invalid' });
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('total downloads (invalid, package version in request)')
   .get('/dt/symfony/symfony/v2.8.0.json')
-  .expectJSON({ name: 'downloads', value: 'invalid' });
-
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('daily downloads (invalid package name)')
   .get('/dd/frodo/is-not-a-package.json')
-  .expectJSON({ name: 'downloads', value: 'invalid' });
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('monthly downloads (invalid package name)')
   .get('/dm/frodo/is-not-a-package.json')
-  .expectJSON({ name: 'downloads', value: 'invalid' });
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 t.create('total downloads (invalid package name)')
   .get('/dt/frodo/is-not-a-package.json')
-  .expectJSON({ name: 'downloads', value: 'invalid' });
-
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 // tests for version endpoint
 
 t.create('version (valid)')
   .get('/v/symfony/symfony.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'packagist',
-    value: isPackagistVersion
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'packagist',
+      value: isPackagistVersion,
+    })
+  )
 
 t.create('version (invalid package name)')
   .get('/v/frodo/is-not-a-package.json')
-  .expectJSON({ name: 'packagist', value: 'invalid' });
-
+  .expectJSON({ name: 'packagist', value: 'invalid' })
 
 // tests for license endpoint
 
 t.create('license (valid)')
   .get('/l/symfony/symfony.json')
-  .expectJSON({ name: 'license', value: 'MIT' });
+  .expectJSON({ name: 'license', value: 'MIT' })
 
 // note: packagist does serve up license at the version level
 // but our endpoint only supports fetching license for the lastest version
 t.create('license (invalid, package version in request)')
   .get('/l/symfony/symfony/v2.8.0.json')
-  .expectJSON({ name: 'license', value: 'invalid' });
+  .expectJSON({ name: 'license', value: 'invalid' })
 
 t.create('license (invalid)')
   .get('/l/frodo/is-not-a-package.json')
-  .expectJSON({ name: 'license', value: 'invalid' });
+  .expectJSON({ name: 'license', value: 'invalid' })
diff --git a/services/php-eye/php-eye.tester.js b/services/php-eye/php-eye.tester.js
index eafecce2b6d8123003e4f5be82610b938dc2a556..5e17684242b0963286d5d49da9bc86dc656cf8f0 100644
--- a/services/php-eye/php-eye.tester.js
+++ b/services/php-eye/php-eye.tester.js
@@ -1,26 +1,29 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const {
-  isPhpVersionReduction
-} = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isPhpVersionReduction } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'php-eye', title: 'PHP version from PHP-Eye' });
-module.exports = t;
+const t = new ServiceTester({
+  id: 'php-eye',
+  title: 'PHP version from PHP-Eye',
+})
+module.exports = t
 
 t.create('gets the package version of symfony')
-    .get('/symfony/symfony.json')
-    .expectJSONTypes(Joi.object().keys({ name: 'PHP tested', value: isPhpVersionReduction }));
+  .get('/symfony/symfony.json')
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'PHP tested', value: isPhpVersionReduction })
+  )
 
 t.create('gets the package version of symfony 2.8')
-    .get('/symfony/symfony/v2.8.0.json')
-    .expectJSON({ name: 'PHP tested', value: '5.3 - 7.0, HHVM' });
+  .get('/symfony/symfony/v2.8.0.json')
+  .expectJSON({ name: 'PHP tested', value: '5.3 - 7.0, HHVM' })
 
 t.create('gets the package version of yii')
-    .get('/yiisoft/yii.json')
-    .expectJSON({ name: 'PHP tested', value: '5.3 - 7.1' });
+  .get('/yiisoft/yii.json')
+  .expectJSON({ name: 'PHP tested', value: '5.3 - 7.1' })
 
 t.create('invalid package name')
-    .get('/frodo/is-not-a-package.json')
-    .expectJSON({ name: 'PHP tested', value: 'invalid' });
+  .get('/frodo/is-not-a-package.json')
+  .expectJSON({ name: 'PHP tested', value: 'invalid' })
diff --git a/services/powershellgallery/powershellgallery.tester.js b/services/powershellgallery/powershellgallery.tester.js
index 199c50782109365c56c3e0c568e44c5a022ee43d..8599a8bb3eff5f182982b910b7dc5359c650a69c 100644
--- a/services/powershellgallery/powershellgallery.tester.js
+++ b/services/powershellgallery/powershellgallery.tester.js
@@ -1,172 +1,205 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isMetric,
   isVPlusDottedVersionNClauses,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators');
-const colorscheme = require('../../lib/colorscheme.json');
+} = require('../test-validators')
+const colorscheme = require('../../lib/colorscheme.json')
 const {
   nuGetV2VersionJsonWithDash,
   nuGetV2VersionJsonFirstCharZero,
-  nuGetV2VersionJsonFirstCharNotZero
-} = require('../nuget-fixtures');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'powershellgallery', title: 'PowerShell Gallery' });
-module.exports = t;
+  nuGetV2VersionJsonFirstCharNotZero,
+} = require('../nuget-fixtures')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({
+  id: 'powershellgallery',
+  title: 'PowerShell Gallery',
+})
+module.exports = t
 
 // downloads
 
 t.create('total downloads (valid)')
   .get('/dt/ACMESharp.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('total downloads (not found)')
   .get('/dt/not-a-real-package.json')
-  .expectJSON({name: 'downloads', value: 'not found'});
+  .expectJSON({ name: 'downloads', value: 'not found' })
 
 t.create('total downloads (connection error)')
   .get('/dt/ACMESharp.json')
   .networkOff()
-  .expectJSON({name: 'downloads', value: 'inaccessible'});
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 t.create('total downloads (unexpected response)')
   .get('/dt/ACMESharp.json')
-  .intercept(nock => nock('https://www.powershellgallery.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://www.powershellgallery.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'downloads', value: 'invalid'});
-
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 // version
 
 t.create('version (valid)')
   .get('/v/ACMESharp.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'powershellgallery',
-    value: isVPlusDottedVersionNClauses,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'powershellgallery',
+      value: isVPlusDottedVersionNClauses,
+    })
+  )
 
 t.create('version (mocked, yellow badge)')
   .get('/v/ACMESharp.json?style=_shields_test')
-  .intercept(nock => nock('https://www.powershellgallery.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonWithDash)
+  .intercept(nock =>
+    nock('https://www.powershellgallery.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonWithDash)
   )
   .expectJSON({
     name: 'powershellgallery',
     value: 'v1.2-beta',
-    colorB: colorscheme.yellow.colorB
-  });
+    colorB: colorscheme.yellow.colorB,
+  })
 
 t.create('version (mocked, orange badge)')
   .get('/v/ACMESharp.json?style=_shields_test')
-  .intercept(nock => nock('https://www.powershellgallery.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharZero)
+  .intercept(nock =>
+    nock('https://www.powershellgallery.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharZero)
   )
   .expectJSON({
     name: 'powershellgallery',
     value: 'v0.35',
-    colorB: colorscheme.orange.colorB
-  });
+    colorB: colorscheme.orange.colorB,
+  })
 
 t.create('version (mocked, blue badge)')
   .get('/v/ACMESharp.json?style=_shields_test')
-  .intercept(nock => nock('https://www.powershellgallery.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharNotZero)
+  .intercept(nock =>
+    nock('https://www.powershellgallery.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharNotZero)
   )
   .expectJSON({
     name: 'powershellgallery',
     value: 'v1.2.7',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('version (not found)')
   .get('/v/not-a-real-package.json')
-  .expectJSON({name: 'powershellgallery', value: 'not found'});
+  .expectJSON({ name: 'powershellgallery', value: 'not found' })
 
 t.create('version (connection error)')
   .get('/v/ACMESharp.json')
   .networkOff()
-  .expectJSON({name: 'powershellgallery', value: 'inaccessible'});
+  .expectJSON({ name: 'powershellgallery', value: 'inaccessible' })
 
 t.create('version (unexpected response)')
   .get('/v/ACMESharp.json')
-  .intercept(nock => nock('https://www.powershellgallery.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://www.powershellgallery.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'powershellgallery', value: 'invalid'});
-
+  .expectJSON({ name: 'powershellgallery', value: 'invalid' })
 
 // version (pre)
 
 t.create('version (pre) (valid)')
   .get('/vpre/ACMESharp.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'powershellgallery',
-    value: isVPlusDottedVersionNClausesWithOptionalSuffix,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'powershellgallery',
+      value: isVPlusDottedVersionNClausesWithOptionalSuffix,
+    })
+  )
 
 t.create('version (pre) (mocked, yellow badge)')
   .get('/vpre/ACMESharp.json?style=_shields_test')
-  .intercept(nock => nock('https://www.powershellgallery.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonWithDash)
+  .intercept(nock =>
+    nock('https://www.powershellgallery.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonWithDash)
   )
   .expectJSON({
     name: 'powershellgallery',
     value: 'v1.2-beta',
-    colorB: colorscheme.yellow.colorB
-  });
+    colorB: colorscheme.yellow.colorB,
+  })
 
 t.create('version (pre) (mocked, orange badge)')
   .get('/vpre/ACMESharp.json?style=_shields_test')
-  .intercept(nock => nock('https://www.powershellgallery.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharZero)
+  .intercept(nock =>
+    nock('https://www.powershellgallery.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharZero)
   )
   .expectJSON({
     name: 'powershellgallery',
     value: 'v0.35',
-    colorB: colorscheme.orange.colorB
-  });
+    colorB: colorscheme.orange.colorB,
+  })
 
 t.create('version (pre) (mocked, blue badge)')
   .get('/vpre/ACMESharp.json?style=_shields_test')
-  .intercept(nock => nock('https://www.powershellgallery.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharNotZero)
+  .intercept(nock =>
+    nock('https://www.powershellgallery.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharNotZero)
   )
   .expectJSON({
     name: 'powershellgallery',
     value: 'v1.2.7',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('version (pre) (not found)')
   .get('/vpre/not-a-real-package.json')
-  .expectJSON({name: 'powershellgallery', value: 'not found'});
+  .expectJSON({ name: 'powershellgallery', value: 'not found' })
 
 t.create('version (pre) (connection error)')
   .get('/vpre/ACMESharp.json')
   .networkOff()
-  .expectJSON({name: 'powershellgallery', value: 'inaccessible'});
+  .expectJSON({ name: 'powershellgallery', value: 'inaccessible' })
 
 t.create('version (pre) (unexpected response)')
   .get('/vpre/ACMESharp.json')
-  .intercept(nock => nock('https://www.powershellgallery.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://www.powershellgallery.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ACMESharp%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'powershellgallery', value: 'invalid'});
+  .expectJSON({ name: 'powershellgallery', value: 'invalid' })
diff --git a/services/pypi/pypi.tester.js b/services/pypi/pypi.tester.js
index 453deb5114e8f840c0404afbff5f5e5b4d38f1a0..fd0a8a2bea3eb84703a7ea67cd30f743202c66a0 100644
--- a/services/pypi/pypi.tester.js
+++ b/services/pypi/pypi.tester.js
@@ -1,18 +1,21 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isSemver } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isSemver } = require('../test-validators')
 
-const isPsycopg2Version = Joi.string().regex(/^v([0-9][.]?)+$/);
+const isPsycopg2Version = Joi.string().regex(/^v([0-9][.]?)+$/)
 
 // These regexes are the same, but defined separately for clarity.
-const isCommaSeperatedPythonVersions = Joi.string().regex(/^([0-9]+.[0-9]+[,]?[ ]?)+$/);
-const isCommaSeperatedDjangoVersions = Joi.string().regex(/^([0-9]+.[0-9]+[,]?[ ]?)+$/);
-
-const t = new ServiceTester({ id: 'pypi', title: 'PyPi badges' });
-module.exports = t;
+const isCommaSeperatedPythonVersions = Joi.string().regex(
+  /^([0-9]+.[0-9]+[,]?[ ]?)+$/
+)
+const isCommaSeperatedDjangoVersions = Joi.string().regex(
+  /^([0-9]+.[0-9]+[,]?[ ]?)+$/
+)
 
+const t = new ServiceTester({ id: 'pypi', title: 'PyPi badges' })
+module.exports = t
 
 /*
   tests for downloads endpoints
@@ -24,28 +27,27 @@ module.exports = t;
 */
 t.create('daily downloads (expected failure)')
   .get('/dd/djangorestframework.json')
-  .expectJSON({ name: 'downloads', value: 'no longer available' });
+  .expectJSON({ name: 'downloads', value: 'no longer available' })
 
 t.create('weekly downloads (expected failure)')
   .get('/dw/djangorestframework.json')
-  .expectJSON({ name: 'downloads', value: 'no longer available' });
+  .expectJSON({ name: 'downloads', value: 'no longer available' })
 
 t.create('monthly downloads (expected failure)')
   .get('/dm/djangorestframework.json')
-  .expectJSON({ name: 'downloads', value: 'no longer available' });
+  .expectJSON({ name: 'downloads', value: 'no longer available' })
 
 t.create('daily downloads (invalid)')
   .get('/dd/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
+  .expectJSON({ name: 'pypi', value: 'invalid' })
 
 t.create('weekly downloads (invalid)')
   .get('/dw/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
+  .expectJSON({ name: 'pypi', value: 'invalid' })
 
 t.create('monthly downloads (invalid)')
   .get('/dm/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
-
+  .expectJSON({ name: 'pypi', value: 'invalid' })
 
 /*
   tests for version endpoint
@@ -63,164 +65,169 @@ t.create('monthly downloads (invalid)')
 */
 t.create('version (semver)')
   .get('/v/requests.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'pypi',
-    value: isSemver
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'pypi',
+      value: isSemver,
+    })
+  )
 
 // ..whereas this project does not folow SemVer
 t.create('version (not semver)')
   .get('/v/psycopg2.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'pypi',
-    value: isPsycopg2Version
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'pypi',
+      value: isPsycopg2Version,
+    })
+  )
 
 t.create('version (invalid)')
   .get('/v/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
-
+  .expectJSON({ name: 'pypi', value: 'invalid' })
 
 // tests for license endpoint
 
 t.create('license (valid, package version in request)')
   .get('/l/requests/2.18.4.json')
-  .expectJSON({ name: 'license', value: 'Apache 2.0' });
+  .expectJSON({ name: 'license', value: 'Apache 2.0' })
 
 t.create('license (valid, no package version specified)')
   .get('/l/requests.json')
-  .expectJSON({ name: 'license', value: 'Apache 2.0' });
+  .expectJSON({ name: 'license', value: 'Apache 2.0' })
 
 t.create('license (invalid)')
   .get('/l/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
-
+  .expectJSON({ name: 'pypi', value: 'invalid' })
 
 // tests for wheel endpoint
 
 t.create('wheel (has wheel, package version in request)')
   .get('/wheel/requests/2.18.4.json')
-  .expectJSON({ name: 'wheel', value: 'yes' });
+  .expectJSON({ name: 'wheel', value: 'yes' })
 
 t.create('wheel (has wheel, no package version specified)')
   .get('/wheel/requests.json')
-  .expectJSON({ name: 'wheel', value: 'yes' });
+  .expectJSON({ name: 'wheel', value: 'yes' })
 
 t.create('wheel (no wheel)')
   .get('/wheel/chai/1.1.2.json')
-  .expectJSON({ name: 'wheel', value: 'no' });
+  .expectJSON({ name: 'wheel', value: 'no' })
 
 t.create('wheel (invalid)')
   .get('/wheel/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
-
+  .expectJSON({ name: 'pypi', value: 'invalid' })
 
 // tests for format endpoint
 
 t.create('format (wheel, package version in request)')
   .get('/format/requests/2.18.4.json')
-  .expectJSON({ name: 'format', value: 'wheel' });
+  .expectJSON({ name: 'format', value: 'wheel' })
 
 t.create('format (wheel, no package version specified)')
   .get('/format/requests.json')
-  .expectJSON({ name: 'format', value: 'wheel' });
+  .expectJSON({ name: 'format', value: 'wheel' })
 
 t.create('format (source)')
   .get('/format/chai/1.1.2.json')
-  .expectJSON({ name: 'format', value: 'source' });
+  .expectJSON({ name: 'format', value: 'source' })
 
 t.create('format (egg)')
   .get('/format/virtualenv/0.8.2.json')
-  .expectJSON({ name: 'format', value: 'egg' });
+  .expectJSON({ name: 'format', value: 'egg' })
 
 t.create('format (invalid)')
   .get('/format/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
-
+  .expectJSON({ name: 'pypi', value: 'invalid' })
 
 // tests for pyversions endpoint
 
 t.create('python versions (valid, package version in request)')
   .get('/pyversions/requests/2.18.4.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'python',
-    value: isCommaSeperatedPythonVersions
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'python',
+      value: isCommaSeperatedPythonVersions,
+    })
+  )
 
 t.create('python versions (valid, no package version specified)')
   .get('/pyversions/requests.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'python',
-    value: isCommaSeperatedPythonVersions
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'python',
+      value: isCommaSeperatedPythonVersions,
+    })
+  )
 
 t.create('python versions (no versions specified)')
   .get('/pyversions/pyshp/1.2.12.json')
-  .expectJSON({ name: 'python', value: 'not found' });
+  .expectJSON({ name: 'python', value: 'not found' })
 
 t.create('python versions (invalid)')
   .get('/pyversions/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
-
+  .expectJSON({ name: 'pypi', value: 'invalid' })
 
 // tests for django versions endpoint
 
 t.create('supported django versions (valid, package version in request)')
   .get('/djversions/djangorestframework/3.7.3.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'django versions',
-    value: isCommaSeperatedDjangoVersions
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'django versions',
+      value: isCommaSeperatedDjangoVersions,
+    })
+  )
 
 t.create('supported django versions (valid, no package version specified)')
   .get('/djversions/djangorestframework.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'django versions',
-    value: isCommaSeperatedDjangoVersions
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'django versions',
+      value: isCommaSeperatedDjangoVersions,
+    })
+  )
 
 t.create('supported django versions (no versions specified)')
   .get('/djversions/django/1.11.json')
-  .expectJSON({ name: 'django versions', value: 'not found' });
+  .expectJSON({ name: 'django versions', value: 'not found' })
 
 t.create('supported django versions (invalid)')
   .get('/djversions/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
-
+  .expectJSON({ name: 'pypi', value: 'invalid' })
 
 // tests for implementation endpoint
 
 t.create('implementation (valid, package version in request)')
   .get('/implementation/beehive/1.0.json')
-  .expectJSON({ name: 'implementation', value: 'cpython, jython, pypy' });
+  .expectJSON({ name: 'implementation', value: 'cpython, jython, pypy' })
 
 t.create('implementation (valid, no package version specified)')
   .get('/implementation/numpy.json')
-  .expectJSON({ name: 'implementation', value: 'cpython' });
+  .expectJSON({ name: 'implementation', value: 'cpython' })
 
 t.create('implementation (not specified)')
   .get('/implementation/chai/1.1.2.json')
-  .expectJSON({ name: 'implementation', value: 'cpython' });
+  .expectJSON({ name: 'implementation', value: 'cpython' })
 
 t.create('implementation (invalid)')
   .get('/implementation/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
-
+  .expectJSON({ name: 'pypi', value: 'invalid' })
 
 // tests for status endpoint
 
 t.create('status (valid, stable, package version in request)')
   .get('/status/django/1.11.json')
-  .expectJSON({name: 'status', value: 'stable' });
+  .expectJSON({ name: 'status', value: 'stable' })
 
 t.create('status (valid, no package version specified)')
   .get('/status/typing.json')
-  .expectJSON({name: 'status', value: 'stable' });
+  .expectJSON({ name: 'status', value: 'stable' })
 
 t.create('status (valid, beta)')
   .get('/status/django/2.0rc1.json')
-  .expectJSON({ name: 'status', value: 'beta' });
+  .expectJSON({ name: 'status', value: 'beta' })
 
 t.create('status (invalid)')
   .get('/status/not-a-package.json')
-  .expectJSON({ name: 'pypi', value: 'invalid' });
+  .expectJSON({ name: 'pypi', value: 'invalid' })
diff --git a/services/readthedocs/readthedocs.tester.js b/services/readthedocs/readthedocs.tester.js
index e024a2679a1ec9d26d50f7206662d94845da9067..7687b9bc7423657d323770232d5c91b1625cd7ca 100644
--- a/services/readthedocs/readthedocs.tester.js
+++ b/services/readthedocs/readthedocs.tester.js
@@ -1,38 +1,44 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { isBuildStatus } = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isBuildStatus } = require('../test-validators')
 
 const t = new ServiceTester({ id: 'readthedocs', title: 'Read the Docs' })
-module.exports = t;
+module.exports = t
 
 t.create('build status')
   .get('/pip.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docs',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docs',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('build status for named version')
   .get('/pip/stable.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docs',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docs',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('build status for named semantic version')
   .get('/scrapy/1.0.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'docs',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'docs',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('unknown project')
   .get('/this-repo/does-not-exist.json')
-  .expectJSON({ name: 'docs', value: 'unknown' });
+  .expectJSON({ name: 'docs', value: 'unknown' })
 
 t.create('connection error')
   .get('/pip.json')
   .networkOff()
-  .expectJSON({ name: 'docs', value: 'inaccessible' });
+  .expectJSON({ name: 'docs', value: 'inaccessible' })
diff --git a/services/redmine/redmine.tester.js b/services/redmine/redmine.tester.js
index 51ebca17b26a0b11c0c53abd081b8b71514bcfa7..d6a1ac95c7e8aa0c9a008eef579866783f3a1afe 100644
--- a/services/redmine/redmine.tester.js
+++ b/services/redmine/redmine.tester.js
@@ -1,59 +1,68 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const {
-    isStarRating
-  } = require('../test-validators');
-  
-const t = new ServiceTester({ id: 'redmine', title: 'Redmine' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isStarRating } = require('../test-validators')
+
+const t = new ServiceTester({ id: 'redmine', title: 'Redmine' })
+module.exports = t
 
 t.create('plugin rating')
   .get('/plugin/rating/redmine_xlsx_format_issue_exporter.json')
-  .intercept(nock => nock('https://www.redmine.org')
-    .get('/plugins/redmine_xlsx_format_issue_exporter.xml')
-    .reply(200,
-        '<redmine-plugin>' + 
-            '<ratings-average type="float">1.23456</ratings-average>' +
-        '</redmine-plugin>'
-    )
+  .intercept(nock =>
+    nock('https://www.redmine.org')
+      .get('/plugins/redmine_xlsx_format_issue_exporter.xml')
+      .reply(
+        200,
+        '<redmine-plugin>' +
+          '<ratings-average type="float">1.23456</ratings-average>' +
+          '</redmine-plugin>'
+      )
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rating',
+      value: Joi.string().regex(/^[0-9]+\.[0-9]+\/5\.0$/),
+    })
   )
-  .expectJSONTypes(Joi.object().keys({
-    name: 'rating',
-    value: Joi.string().regex(/^[0-9]+\.[0-9]+\/5\.0$/)
-  }));
 
 t.create('plugin stars')
-.get('/plugin/stars/redmine_xlsx_format_issue_exporter.json')
-.intercept(nock => nock('https://www.redmine.org')
-  .get('/plugins/redmine_xlsx_format_issue_exporter.xml')
-  .reply(200,
-      '<redmine-plugin>' + 
+  .get('/plugin/stars/redmine_xlsx_format_issue_exporter.json')
+  .intercept(nock =>
+    nock('https://www.redmine.org')
+      .get('/plugins/redmine_xlsx_format_issue_exporter.xml')
+      .reply(
+        200,
+        '<redmine-plugin>' +
           '<ratings-average type="float">1.23456</ratings-average>' +
-      '</redmine-plugin>'
+          '</redmine-plugin>'
+      )
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'stars',
+      value: isStarRating,
+    })
   )
-)
-.expectJSONTypes(Joi.object().keys({
-  name: 'stars',
-  value: isStarRating
-}));
 
 t.create('plugin not found')
   .get('/plugin/rating/plugin_not_found.json')
-  .intercept(nock => nock('https://www.redmine.org')
-    .get('/plugins/plugin_not_found.xml')
-    .reply(404, '')
+  .intercept(nock =>
+    nock('https://www.redmine.org')
+      .get('/plugins/plugin_not_found.xml')
+      .reply(404, '')
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rating',
+      value: 'invalid',
+    })
   )
-  .expectJSONTypes(Joi.object().keys({
-    name: 'rating',
-    value: 'invalid'
-  }));
 
 t.create('connection error')
   .get('/plugin/rating/redmine_xlsx_format_issue_exporter.json')
   .networkOff()
   .expectJSON({
-      name: 'rating',
-      value: 'inaccessible'
-  });
+    name: 'rating',
+    value: 'inaccessible',
+  })
diff --git a/services/requires/requires.tester.js b/services/requires/requires.tester.js
index b1718a1a0d4ad0b6c7d9860887554edfa2ffc38f..6640833acaf92c78de7859c5604288b05060ade1 100644
--- a/services/requires/requires.tester.js
+++ b/services/requires/requires.tester.js
@@ -1,42 +1,48 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
 
-const isRequireStatus = Joi.string().regex(/^(up to date|outdated|insecure|unknown)$/);
-
-const t = new ServiceTester({ id: 'requires', title: 'Requires.io' });
-module.exports = t;
+const isRequireStatus = Joi.string().regex(
+  /^(up to date|outdated|insecure|unknown)$/
+)
 
+const t = new ServiceTester({ id: 'requires', title: 'Requires.io' })
+module.exports = t
 
 t.create('requirements (valid, without branch)')
   .get('/github/celery/celery.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'requirements',
-    value: isRequireStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'requirements',
+      value: isRequireStatus,
+    })
+  )
 
 t.create('requirements (valid, with branch)')
   .get('/github/celery/celery/master.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'requirements',
-    value: isRequireStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'requirements',
+      value: isRequireStatus,
+    })
+  )
 
 t.create('requirements (not found)')
   .get('/github/PyvesB/EmptyRepo.json')
-  .expectJSON({name: 'requirements', value: 'not found'});
+  .expectJSON({ name: 'requirements', value: 'not found' })
 
 t.create('requirements (connection error)')
   .get('/github/celery/celery.json')
   .networkOff()
-  .expectJSON({name: 'requirements', value: 'inaccessible'});
+  .expectJSON({ name: 'requirements', value: 'inaccessible' })
 
 t.create('requirements (unexpected response)')
   .get('/github/celery/celery.json')
-  .intercept(nock => nock('https://requires.io/')
-    .get('/api/v1/status/github/celery/celery')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://requires.io/')
+      .get('/api/v1/status/github/celery/celery')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'requirements', value: 'invalid'});
+  .expectJSON({ name: 'requirements', value: 'invalid' })
diff --git a/services/resharper/resharper.tester.js b/services/resharper/resharper.tester.js
index c20526e5f6fca1819f93dd98b18622f5449113ee..707e630b9701c2921c4464d988b28e67d95da883 100644
--- a/services/resharper/resharper.tester.js
+++ b/services/resharper/resharper.tester.js
@@ -1,172 +1,202 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isMetric,
   isVPlusDottedVersionNClauses,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators');
-const colorscheme = require('../../lib/colorscheme.json');
+} = require('../test-validators')
+const colorscheme = require('../../lib/colorscheme.json')
 const {
   nuGetV2VersionJsonWithDash,
   nuGetV2VersionJsonFirstCharZero,
-  nuGetV2VersionJsonFirstCharNotZero
-} = require('../nuget-fixtures');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'resharper', title: 'ReSharper' });
-module.exports = t;
+  nuGetV2VersionJsonFirstCharNotZero,
+} = require('../nuget-fixtures')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'resharper', title: 'ReSharper' })
+module.exports = t
 
 // downloads
 
 t.create('total downloads (valid)')
   .get('/dt/ReSharper.Nuke.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('total downloads (not found)')
   .get('/dt/not-a-real-package.json')
-  .expectJSON({name: 'downloads', value: 'not found'});
+  .expectJSON({ name: 'downloads', value: 'not found' })
 
 t.create('total downloads (connection error)')
   .get('/dt/ReSharper.Nuke.json')
   .networkOff()
-  .expectJSON({name: 'downloads', value: 'inaccessible'});
+  .expectJSON({ name: 'downloads', value: 'inaccessible' })
 
 t.create('total downloads (unexpected response)')
   .get('/dt/ReSharper.Nuke.json')
-  .intercept(nock => nock('https://resharper-plugins.jetbrains.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://resharper-plugins.jetbrains.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'downloads', value: 'invalid'});
-
+  .expectJSON({ name: 'downloads', value: 'invalid' })
 
 // version
 
 t.create('version (valid)')
   .get('/v/ReSharper.Nuke.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'resharper',
-    value: isVPlusDottedVersionNClauses,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'resharper',
+      value: isVPlusDottedVersionNClauses,
+    })
+  )
 
 t.create('version (mocked, yellow badge)')
   .get('/v/ReSharper.Nuke.json?style=_shields_test')
-  .intercept(nock => nock('https://resharper-plugins.jetbrains.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonWithDash)
+  .intercept(nock =>
+    nock('https://resharper-plugins.jetbrains.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonWithDash)
   )
   .expectJSON({
     name: 'resharper',
     value: 'v1.2-beta',
-    colorB: colorscheme.yellow.colorB
-  });
+    colorB: colorscheme.yellow.colorB,
+  })
 
 t.create('version (mocked, orange badge)')
   .get('/v/ReSharper.Nuke.json?style=_shields_test')
-  .intercept(nock => nock('https://resharper-plugins.jetbrains.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharZero)
+  .intercept(nock =>
+    nock('https://resharper-plugins.jetbrains.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharZero)
   )
   .expectJSON({
     name: 'resharper',
     value: 'v0.35',
-    colorB: colorscheme.orange.colorB
-  });
+    colorB: colorscheme.orange.colorB,
+  })
 
 t.create('version (mocked, blue badge)')
   .get('/v/ReSharper.Nuke.json?style=_shields_test')
-  .intercept(nock => nock('https://resharper-plugins.jetbrains.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharNotZero)
+  .intercept(nock =>
+    nock('https://resharper-plugins.jetbrains.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharNotZero)
   )
   .expectJSON({
     name: 'resharper',
     value: 'v1.2.7',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('version (not found)')
   .get('/v/not-a-real-package.json')
-  .expectJSON({name: 'resharper', value: 'not found'});
+  .expectJSON({ name: 'resharper', value: 'not found' })
 
 t.create('version (connection error)')
   .get('/v/ReSharper.Nuke.json')
   .networkOff()
-  .expectJSON({name: 'resharper', value: 'inaccessible'});
+  .expectJSON({ name: 'resharper', value: 'inaccessible' })
 
 t.create('version (unexpected response)')
   .get('/v/ReSharper.Nuke.json')
-  .intercept(nock => nock('https://resharper-plugins.jetbrains.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsLatestVersion%20eq%20true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://resharper-plugins.jetbrains.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsLatestVersion%20eq%20true'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'resharper', value: 'invalid'});
-
+  .expectJSON({ name: 'resharper', value: 'invalid' })
 
 // version (pre)
 
 t.create('version (pre) (valid)')
   .get('/vpre/ReSharper.Nuke.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'resharper',
-    value: isVPlusDottedVersionNClausesWithOptionalSuffix,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'resharper',
+      value: isVPlusDottedVersionNClausesWithOptionalSuffix,
+    })
+  )
 
 t.create('version (pre) (mocked, yellow badge)')
   .get('/vpre/ReSharper.Nuke.json?style=_shields_test')
-  .intercept(nock => nock('https://resharper-plugins.jetbrains.com')
-  .get("/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonWithDash)
+  .intercept(nock =>
+    nock('https://resharper-plugins.jetbrains.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonWithDash)
   )
   .expectJSON({
     name: 'resharper',
     value: 'v1.2-beta',
-    colorB: colorscheme.yellow.colorB
-  });
+    colorB: colorscheme.yellow.colorB,
+  })
 
 t.create('version (pre) (mocked, orange badge)')
   .get('/vpre/ReSharper.Nuke.json?style=_shields_test')
-  .intercept(nock => nock('https://resharper-plugins.jetbrains.com')
-  .get("/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharZero)
+  .intercept(nock =>
+    nock('https://resharper-plugins.jetbrains.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharZero)
   )
   .expectJSON({
     name: 'resharper',
     value: 'v0.35',
-    colorB: colorscheme.orange.colorB
-  });
+    colorB: colorscheme.orange.colorB,
+  })
 
 t.create('version (pre) (mocked, blue badge)')
   .get('/vpre/ReSharper.Nuke.json?style=_shields_test')
-  .intercept(nock => nock('https://resharper-plugins.jetbrains.com')
-  .get("/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(200, nuGetV2VersionJsonFirstCharNotZero)
+  .intercept(nock =>
+    nock('https://resharper-plugins.jetbrains.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(200, nuGetV2VersionJsonFirstCharNotZero)
   )
   .expectJSON({
     name: 'resharper',
     value: 'v1.2.7',
-    colorB: colorscheme.blue.colorB
-  });
+    colorB: colorscheme.blue.colorB,
+  })
 
 t.create('version (pre) (not found)')
   .get('/vpre/not-a-real-package.json')
-  .expectJSON({name: 'resharper', value: 'not found'});
+  .expectJSON({ name: 'resharper', value: 'not found' })
 
 t.create('version (pre) (connection error)')
   .get('/vpre/ReSharper.Nuke.json')
   .networkOff()
-  .expectJSON({name: 'resharper', value: 'inaccessible'});
+  .expectJSON({ name: 'resharper', value: 'inaccessible' })
 
 t.create('version (pre) (unexpected response)')
   .get('/vpre/ReSharper.Nuke.json')
-  .intercept(nock => nock('https://resharper-plugins.jetbrains.com')
-    .get("/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsAbsoluteLatestVersion%20eq%20true")
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://resharper-plugins.jetbrains.com')
+      .get(
+        '/api/v2/Packages()?$filter=Id%20eq%20%27ReSharper.Nuke%27%20and%20IsAbsoluteLatestVersion%20eq%20true'
+      )
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'resharper', value: 'invalid'});
+  .expectJSON({ name: 'resharper', value: 'invalid' })
diff --git a/services/response-fixtures.js b/services/response-fixtures.js
index ac5efaa5b73f726a7dae650b6fa6708f19de3926..49ba6d8a7f0ba8758ff7808a3edadb3e082e9661 100644
--- a/services/response-fixtures.js
+++ b/services/response-fixtures.js
@@ -1,13 +1,9 @@
-'use strict';
+'use strict'
 
 const invalidJSON = function() {
-  return [
-    200,
-    '{{{{{invalid json}}',
-    { 'Content-Type': 'application/json' }
-  ];
-};
+  return [200, '{{{{{invalid json}}', { 'Content-Type': 'application/json' }]
+}
 
 module.exports = {
-  invalidJSON
-};
+  invalidJSON,
+}
diff --git a/services/scrutinizer/scrutinizer.tester.js b/services/scrutinizer/scrutinizer.tester.js
index c8199574eb2a44d1e85ff8d1bd15439fccfb953f..baa00e0185ce0840084469db77ac9eabee2ef47c 100644
--- a/services/scrutinizer/scrutinizer.tester.js
+++ b/services/scrutinizer/scrutinizer.tester.js
@@ -1,77 +1,88 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const {
-  isBuildStatus,
-  isIntegerPercentage
-} = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isBuildStatus, isIntegerPercentage } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'scrutinizer', title: 'Scrutinizer' });
-module.exports = t;
+const t = new ServiceTester({ id: 'scrutinizer', title: 'Scrutinizer' })
+module.exports = t
 
 t.create('code quality')
   .get('/g/filp/whoops.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'code quality',
-    value: Joi.number().positive(),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'code quality',
+      value: Joi.number().positive(),
+    })
+  )
 
 t.create('code quality (branch)')
   .get('/g/phpmyadmin/phpmyadmin/master.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'code quality',
-    value: Joi.number().positive(),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'code quality',
+      value: Joi.number().positive(),
+    })
+  )
 
 t.create('code coverage')
   .get('/coverage/g/filp/whoops.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'coverage',
-    value: isIntegerPercentage,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'coverage',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('code coverage (branch)')
   .get('/coverage/g/doctrine/doctrine2/master.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'coverage',
-    value: isIntegerPercentage,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'coverage',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('build')
   .get('/build/g/filp/whoops.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('build (branch)')
   .get('/build/g/phpmyadmin/phpmyadmin/master.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('project not found')
   .get('/build/g/does-not-exist/does-not-exist.json')
   .expectJSON({
-     name: 'build',
-     value: 'project or branch not found',
-  });
+    name: 'build',
+    value: 'project or branch not found',
+  })
 
 t.create('code coverage unknown')
   .get('/coverage/g/phpmyadmin/phpmyadmin/master.json')
   .expectJSON({
-     name: 'coverage',
-     value: 'unknown',
-  });
+    name: 'coverage',
+    value: 'unknown',
+  })
 
 t.create('unexpected response data')
   .get('/coverage/g/filp/whoops.json')
-  .intercept(nock => nock('https://scrutinizer-ci.com')
-    .get('/api/repositories/g/filp/whoops')
-    .reply(200, '{"unexpected":"data"}'))
+  .intercept(nock =>
+    nock('https://scrutinizer-ci.com')
+      .get('/api/repositories/g/filp/whoops')
+      .reply(200, '{"unexpected":"data"}')
+  )
   .expectJSON({
-     name: 'coverage',
-     value: 'invalid',
-  });
+    name: 'coverage',
+    value: 'invalid',
+  })
diff --git a/services/service-tester.js b/services/service-tester.js
index 78f182583c93434990d80baec710e2d88b07d5d0..cb4933997d18da97c887af43e84d048d85dcdef5 100644
--- a/services/service-tester.js
+++ b/services/service-tester.js
@@ -1,7 +1,7 @@
-'use strict';
+'use strict'
 
-const frisby = require('icedfrisby-nock')(require('icedfrisby'));
-const config = require('../lib/test-config');
+const frisby = require('icedfrisby-nock')(require('icedfrisby'))
+const config = require('../lib/test-config')
 
 /**
  * Encapsulate a suite of tests. Create new tests using create() and register
@@ -14,23 +14,22 @@ class ServiceTester {
    *   Mocha output. The `path` is the path prefix which is automatically
    *   prepended to each tested URI. The default is `/${attrs.id}`.
    */
-  constructor (attrs) {
+  constructor(attrs) {
     Object.assign(this, {
       id: attrs.id,
       title: attrs.title,
-      pathPrefix: attrs.pathPrefix === undefined
-        ? `/${attrs.id}`
-        : attrs.pathPrefix,
+      pathPrefix:
+        attrs.pathPrefix === undefined ? `/${attrs.id}` : attrs.pathPrefix,
       specs: [],
-      _only: false
-    });
+      _only: false,
+    })
   }
 
   /**
    * Invoked before each test. This is a stub which can be overridden on
    * instances.
    */
-  beforeEach () {}
+  beforeEach() {}
 
   /**
    * Create a new test. The hard work is delegated to IcedFrisby.
@@ -40,34 +39,39 @@ class ServiceTester {
    * invoked automatically by the tester.
    * @param msg The name of the test
    */
-  create (msg) {
-    const spec = frisby.create(msg)
+  create(msg) {
+    const spec = frisby
+      .create(msg)
       .baseUri(`http://localhost:${config.port}${this.pathPrefix}`)
-      .before(() => { this.beforeEach(); });
+      .before(() => {
+        this.beforeEach()
+      })
 
-    this.specs.push(spec);
+    this.specs.push(spec)
 
-    return spec;
+    return spec
   }
 
   /**
    * Run only this tester. This can be invoked using the --only argument to
    * the CLI, or directly on the tester.
    */
-  only () {
-    this._only = true;
+  only() {
+    this._only = true
   }
 
   /**
    * Register the tests with Mocha.
    */
-  toss () {
-    const specs = this.specs;
+  toss() {
+    const specs = this.specs
 
-    const fn = this._only ? describe.only : describe;
-    fn(this.title, function () {
-      specs.forEach(spec => { spec.toss(); });
-    });
+    const fn = this._only ? describe.only : describe
+    fn(this.title, function() {
+      specs.forEach(spec => {
+        spec.toss()
+      })
+    })
   }
 }
-module.exports = ServiceTester;
+module.exports = ServiceTester
diff --git a/services/shippable/shippable.tester.js b/services/shippable/shippable.tester.js
index 0ccf7ee1577ba24b2d7d2627e9ca6587dc3aec4d..55bacd0f1e3a25e892b12ff4965af2dd182984f1 100644
--- a/services/shippable/shippable.tester.js
+++ b/services/shippable/shippable.tester.js
@@ -1,53 +1,58 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
-const { isBuildStatus } = require('../test-validators');
-
-const t = new ServiceTester({ id: 'shippable', title: 'Shippable CI' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
+const { isBuildStatus } = require('../test-validators')
 
+const t = new ServiceTester({ id: 'shippable', title: 'Shippable CI' })
+module.exports = t
 
 t.create('build status (valid, without branch)')
   .get('/5444c5ecb904a4b21567b0ff.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: isBuildStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: isBuildStatus,
+    })
+  )
 
 t.create('build status (valid, with branch)')
   .get('/5444c5ecb904a4b21567b0ff/master.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: isBuildStatus
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: isBuildStatus,
+    })
+  )
 
 t.create('build status (branch not found)')
   .get('/5444c5ecb904a4b21567b0ff/not-a-branch.json')
-  .expectJSON({name: 'build', value: 'branch not found'});
+  .expectJSON({ name: 'build', value: 'branch not found' })
 
 t.create('build status (not found)')
   .get('/not-a-build.json')
-  .expectJSON({name: 'build', value: 'not found'});
+  .expectJSON({ name: 'build', value: 'not found' })
 
 t.create('build status (connection error)')
   .get('/5444c5ecb904a4b21567b0ff.json')
   .networkOff()
-  .expectJSON({name: 'build', value: 'inaccessible'});
+  .expectJSON({ name: 'build', value: 'inaccessible' })
 
 t.create('build status (unexpected response)')
   .get('/5444c5ecb904a4b21567b0ff.json')
-  .intercept(nock => nock('https://api.shippable.com/')
-    .get('/projects/5444c5ecb904a4b21567b0ff/branchRunStatus')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.shippable.com/')
+      .get('/projects/5444c5ecb904a4b21567b0ff/branchRunStatus')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'build', value: 'invalid'});
+  .expectJSON({ name: 'build', value: 'invalid' })
 
 t.create('build status (unexpected status code)')
   .get('/5444c5ecb904a4b21567b0ff.json')
-  .intercept(nock => nock('https://api.shippable.com/')
-    .get('/projects/5444c5ecb904a4b21567b0ff/branchRunStatus')
-    .reply(200, '[{ "branchName": "master", "statusCode": 63 }]')
+  .intercept(nock =>
+    nock('https://api.shippable.com/')
+      .get('/projects/5444c5ecb904a4b21567b0ff/branchRunStatus')
+      .reply(200, '[{ "branchName": "master", "statusCode": 63 }]')
   )
-  .expectJSON({name: 'build', value: 'invalid'});
+  .expectJSON({ name: 'build', value: 'invalid' })
diff --git a/services/snap-ci/snap-ci.tester.js b/services/snap-ci/snap-ci.tester.js
index 0de847160addcc354a67e610ba889909a885877b..baeaa01e1ded55c8e77d0f720e01bfd06079dfb4 100644
--- a/services/snap-ci/snap-ci.tester.js
+++ b/services/snap-ci/snap-ci.tester.js
@@ -1,13 +1,13 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
+const ServiceTester = require('../service-tester')
 
-const t = new ServiceTester({ id: 'snap-ci', title: 'Snap CI' });
-module.exports = t;
+const t = new ServiceTester({ id: 'snap-ci', title: 'Snap CI' })
+module.exports = t
 
 t.create('no longer available (previously build state)')
   .get('/snap-ci/ThoughtWorksStudios/eb_deployer/master.json')
   .expectJSON({
     name: 'snap CI',
     value: 'no longer available',
-  });
+  })
diff --git a/services/sonarqube/sonarqube.tester.js b/services/sonarqube/sonarqube.tester.js
index b1c8c451393867918bd4405a08edbb4ffa04657d..02f49977b619ce4eb6a6737d4ba2aa88044e2977 100644
--- a/services/sonarqube/sonarqube.tester.js
+++ b/services/sonarqube/sonarqube.tester.js
@@ -1,46 +1,64 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const {
-  isIntegerPercentage,
-} = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isIntegerPercentage } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'sonar', title: 'SonarQube' });
-module.exports = t;
+const t = new ServiceTester({ id: 'sonar', title: 'SonarQube' })
+module.exports = t
 
 t.create('Tech Debt')
-  .get('/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/tech_debt.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'tech debt',
-    value: isIntegerPercentage
-  }));
+  .get(
+    '/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/tech_debt.json'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'tech debt',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('Coverage')
-  .get('/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/coverage.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'coverage',
-    value: isIntegerPercentage
-  }));
+  .get(
+    '/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/coverage.json'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'coverage',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('Tech Debt (legacy API supported)')
-  .get('/4.2/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/tech_debt.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'tech debt',
-    value: isIntegerPercentage
-  }));
+  .get(
+    '/4.2/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/tech_debt.json'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'tech debt',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('Coverage (legacy API supported)')
-  .get('/4.2/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/coverage.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'coverage',
-    value: isIntegerPercentage
-  }));
+  .get(
+    '/4.2/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/coverage.json'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'coverage',
+      value: isIntegerPercentage,
+    })
+  )
 
 t.create('Tech Debt (legacy API unsupported)')
-  .get('/4.2/https/sonarqube.com/com.github.dannil:scb-java-client/tech_debt.json')
-  .expectJSON({ name: 'tech debt', value: 'invalid' });
+  .get(
+    '/4.2/https/sonarqube.com/com.github.dannil:scb-java-client/tech_debt.json'
+  )
+  .expectJSON({ name: 'tech debt', value: 'invalid' })
 
 t.create('Coverage (legacy API unsupported)')
-  .get('/4.2/https/sonarqube.com/com.github.dannil:scb-java-client/coverage.json')
-  .expectJSON({ name: 'coverage', value: 'invalid' });
+  .get(
+    '/4.2/https/sonarqube.com/com.github.dannil:scb-java-client/coverage.json'
+  )
+  .expectJSON({ name: 'coverage', value: 'invalid' })
diff --git a/services/sourceforge/sourceforge.tester.js b/services/sourceforge/sourceforge.tester.js
index b045812248fa7c412eec77f44b089597872c4b62..b07eced536f98da10033e155a163c4bf72b4d4f6 100644
--- a/services/sourceforge/sourceforge.tester.js
+++ b/services/sourceforge/sourceforge.tester.js
@@ -1,54 +1,59 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const {
-	  isMetric,
-	  isMetricOverTimePeriod
-} = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isMetric, isMetricOverTimePeriod } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'sourceforge', title: 'SourceForge' });
-module.exports = t;
+const t = new ServiceTester({ id: 'sourceforge', title: 'SourceForge' })
+module.exports = t
 
 t.create('total downloads')
   .get('/dt/sevenzip.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('monthly downloads')
   .get('/dm/sevenzip.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriod,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriod,
+    })
+  )
 
 t.create('weekly downloads')
   .get('/dw/sevenzip.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriod,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriod,
+    })
+  )
 
 t.create('daily downloads')
   .get('/dd/sevenzip.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetricOverTimePeriod,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetricOverTimePeriod,
+    })
+  )
 
 t.create('invalid project')
   .get('/dd/invalid.json')
   .expectJSON({
     name: 'downloads',
     value: 'invalid',
-  });
+  })
 
 t.create('total downloads (connection error)')
   .get('/dt/sevenzip.json')
   .networkOff()
   .expectJSON({
     name: 'downloads',
-    value: 'inaccessible'
-  });
+    value: 'inaccessible',
+  })
diff --git a/services/suggest/suggest.tester.js b/services/suggest/suggest.tester.js
index 2a7c9f2eea13e4124bc09044e9bf556900fee462..fbac8b593718a3a4a3ed2eaebae6895335236afa 100644
--- a/services/suggest/suggest.tester.js
+++ b/services/suggest/suggest.tester.js
@@ -1,13 +1,17 @@
-'use strict';
+'use strict'
 
 // These tests are for the badge-suggestion endpoint in lib/suggest.js. This
 // endpoint is called from frontend/components/suggestion-and-search.js.
 
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
 
-const t = new ServiceTester({ id: 'suggest', title: 'suggest', pathPrefix: '/$suggest' });
-module.exports = t;
+const t = new ServiceTester({
+  id: 'suggest',
+  title: 'suggest',
+  pathPrefix: '/$suggest',
+})
+module.exports = t
 
 t.create('issues, forks, stars and twitter')
   .get('/v1?url=' + encodeURIComponent('https://github.com/atom/atom'))
@@ -15,64 +19,71 @@ t.create('issues, forks, stars and twitter')
   .expectJSON('badges.?', {
     name: 'GitHub issues',
     link: 'https://github.com/atom/atom/issues',
-    badge: 'https://img.shields.io/github/issues/atom/atom.svg'
+    badge: 'https://img.shields.io/github/issues/atom/atom.svg',
   })
   .expectJSON('badges.?', {
     name: 'GitHub forks',
     link: 'https://github.com/atom/atom/network',
-    badge: 'https://img.shields.io/github/forks/atom/atom.svg'
+    badge: 'https://img.shields.io/github/forks/atom/atom.svg',
   })
   .expectJSON('badges.?', {
     name: 'GitHub stars',
     link: 'https://github.com/atom/atom/stargazers',
-    badge: 'https://img.shields.io/github/stars/atom/atom.svg'
+    badge: 'https://img.shields.io/github/stars/atom/atom.svg',
   })
   .expectJSON('badges.?', {
     name: 'Twitter',
-    link: 'https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Fatom%2Fatom',
-    badge: 'https://img.shields.io/twitter/url/https/github.com/atom/atom.svg?style=social'
-  });
+    link:
+      'https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Fatom%2Fatom',
+    badge:
+      'https://img.shields.io/twitter/url/https/github.com/atom/atom.svg?style=social',
+  })
 
 t.create('license')
   .get('/v1?url=' + encodeURIComponent('https://github.com/atom/atom'))
   .expectJSON('badges.?', {
     name: 'GitHub license',
     link: 'https://github.com/atom/atom/blob/master/LICENSE.md',
-    badge: 'https://img.shields.io/github/license/atom/atom.svg'
-  });
+    badge: 'https://img.shields.io/github/license/atom/atom.svg',
+  })
 
 t.create('license for non-existing project')
   .get('/v1?url=' + encodeURIComponent('https://github.com/atom/atom'))
-  .intercept(nock => nock('https://api.github.com')
-    .get(/\/repos\/atom\/atom\/license/)
-    .reply(404))
+  .intercept(nock =>
+    nock('https://api.github.com')
+      .get(/\/repos\/atom\/atom\/license/)
+      .reply(404)
+  )
   .expectJSON('badges.?', {
     name: 'GitHub license',
     link: 'https://github.com/atom/atom',
-    badge: 'https://img.shields.io/github/license/atom/atom.svg'
-  });
+    badge: 'https://img.shields.io/github/license/atom/atom.svg',
+  })
 
 t.create('license when json response is invalid')
   .get('/v1?url=' + encodeURIComponent('https://github.com/atom/atom'))
-  .intercept(nock => nock('https://api.github.com')
-    .get(/\/repos\/atom\/atom\/license/)
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.github.com')
+      .get(/\/repos\/atom\/atom\/license/)
+      .reply(invalidJSON)
   )
   .expectJSON('badges.?', {
     name: 'GitHub license',
     link: 'https://github.com/atom/atom',
-    badge: 'https://img.shields.io/github/license/atom/atom.svg'
-  });
+    badge: 'https://img.shields.io/github/license/atom/atom.svg',
+  })
 
 t.create('license when html_url not found in GitHub api response')
   .get('/v1?url=' + encodeURIComponent('https://github.com/atom/atom'))
-  .intercept(nock => nock('https://api.github.com')
-    .get(/\/repos\/atom\/atom\/license/)
-    .reply(200, {
-      license: 'MIT'
-    }))
+  .intercept(nock =>
+    nock('https://api.github.com')
+      .get(/\/repos\/atom\/atom\/license/)
+      .reply(200, {
+        license: 'MIT',
+      })
+  )
   .expectJSON('badges.?', {
     name: 'GitHub license',
     link: 'https://github.com/atom/atom',
-    badge: 'https://img.shields.io/github/license/atom/atom.svg'
-  });
+    badge: 'https://img.shields.io/github/license/atom/atom.svg',
+  })
diff --git a/services/test-validators.js b/services/test-validators.js
index 9211f24e3791d0ba016d3791d3e4182bc5e49747..6f7d992a7a9e2a07b650b36c2230132da3693963 100644
--- a/services/test-validators.js
+++ b/services/test-validators.js
@@ -1,4 +1,4 @@
-'use strict';
+'use strict'
 
 /*
   Note:
@@ -7,24 +7,26 @@
   should be declared in that service's test file.
 */
 
-const Joi = require('joi');
-const semverRegex = require('semver-regex')();
+const Joi = require('joi')
+const semverRegex = require('semver-regex')()
 
-const withRegex = (re) => Joi.string().regex(re);
+const withRegex = re => Joi.string().regex(re)
 
-const isSemver = withRegex(semverRegex);
+const isSemver = withRegex(semverRegex)
 
-const isVPlusTripleDottedVersion = withRegex(/^v[0-9]+.[0-9]+.[0-9]+$/);
+const isVPlusTripleDottedVersion = withRegex(/^v[0-9]+.[0-9]+.[0-9]+$/)
 
-const isVPlusDottedVersionAtLeastOne = withRegex(/^v\d+(\.\d+)?(\.\d+)?$/);
+const isVPlusDottedVersionAtLeastOne = withRegex(/^v\d+(\.\d+)?(\.\d+)?$/)
 
 // matches a version number with N 'clauses' e.g: v1.2 or v1.22.7.392 are valid
-const isVPlusDottedVersionNClauses = withRegex(/^v\d+(\.\d+)*$/);
+const isVPlusDottedVersionNClauses = withRegex(/^v\d+(\.\d+)*$/)
 
 // matches a version number with N 'clauses'
 // and an optional text suffix
 // e.g: -beta, -preview1, -release-candidate etc
-const isVPlusDottedVersionNClausesWithOptionalSuffix = withRegex(/^v\d+(\.\d+)*(-.*)?$/);
+const isVPlusDottedVersionNClausesWithOptionalSuffix = withRegex(
+  /^v\d+(\.\d+)*(-.*)?$/
+)
 
 // Simple regex for test Composer versions rule
 // https://getcomposer.org/doc/articles/versions.md
@@ -38,40 +40,76 @@ const isVPlusDottedVersionNClausesWithOptionalSuffix = withRegex(/^v\d+(\.\d+)*(
 // This regex not support branches, minimum-stability, ref and any (*)
 // https://getcomposer.org/doc/04-schema.md#package-links
 // https://getcomposer.org/doc/04-schema.md#minimum-stability
-const isComposerVersion = withRegex(/^\s*(>=|>|<|<=|!=|\^|~)?\d+(\.(\*|(\d+(\.(\d+|\*))?)))?((\s*\|\|)?\s*(>=|>|<|<=|!=|\^|~)?\d+(\.(\*|(\d+(\.(\d+|\*))?)))?)*\s*$/);
+const isComposerVersion = withRegex(
+  /^\s*(>=|>|<|<=|!=|\^|~)?\d+(\.(\*|(\d+(\.(\d+|\*))?)))?((\s*\|\|)?\s*(>=|>|<|<=|!=|\^|~)?\d+(\.(\*|(\d+(\.(\d+|\*))?)))?)*\s*$/
+)
 
 // Regex for validate php-version.versionReduction()
 // >= 7
 // >= 7.1
 // 5.4, 5.6, 7.2
 // 5.4 - 7.1, HHVM
-const isPhpVersionReduction = withRegex(/^((>= \d+(\.\d+)?)|(\d+\.\d+(, \d+\.\d+)*)|(\d+\.\d+ \\- \d+\.\d+))(, HHVM)?$/);
+const isPhpVersionReduction = withRegex(
+  /^((>= \d+(\.\d+)?)|(\d+\.\d+(, \d+\.\d+)*)|(\d+\.\d+ \\- \d+\.\d+))(, HHVM)?$/
+)
 
-const isStarRating = withRegex(/^(?=.{5}$)(\u2605{0,5}[\u00BC\u00BD\u00BE]?\u2606{0,5})$/);
+const isStarRating = withRegex(
+  /^(?=.{5}$)(\u2605{0,5}[\u00BC\u00BD\u00BE]?\u2606{0,5})$/
+)
 
 // Required to be > 0, because accepting zero masks many problems.
-const isMetric = withRegex(/^[1-9][0-9]*[kMGTPEZY]?$/);
+const isMetric = withRegex(/^[1-9][0-9]*[kMGTPEZY]?$/)
 
-const isMetricOpenIssues = withRegex(/^[1-9][0-9]*[kMGTPEZY]? open$/);
+const isMetricOpenIssues = withRegex(/^[1-9][0-9]*[kMGTPEZY]? open$/)
 
-const isMetricOverTimePeriod = withRegex(/^[1-9][0-9]*[kMGTPEZY]?\/(year|month|4 weeks|week|day)$/);
+const isMetricOverTimePeriod = withRegex(
+  /^[1-9][0-9]*[kMGTPEZY]?\/(year|month|4 weeks|week|day)$/
+)
 
-const isIntegerPercentage = withRegex(/^[0-9]+%$/);
-const isDecimalPercentage = withRegex(/^[0-9]+\.[0-9]*%$/);
-const isPercentage = Joi.alternatives().try(isIntegerPercentage, isDecimalPercentage);
+const isIntegerPercentage = withRegex(/^[0-9]+%$/)
+const isDecimalPercentage = withRegex(/^[0-9]+\.[0-9]*%$/)
+const isPercentage = Joi.alternatives().try(
+  isIntegerPercentage,
+  isDecimalPercentage
+)
 
-const isFileSize = withRegex(/^[0-9]*[.]?[0-9]+\s(B|kB|MB|GB|TB|PB|EB|ZB|YB)$/);
+const isFileSize = withRegex(/^[0-9]*[.]?[0-9]+\s(B|kB|MB|GB|TB|PB|EB|ZB|YB)$/)
 
 const isFormattedDate = Joi.alternatives().try(
   Joi.equal('today', 'yesterday'),
   Joi.string().regex(/^last (sun|mon|tues|wednes|thurs|fri|satur)day$/),
-  Joi.string().regex(/^(january|february|march|april|may|june|july|august|september|october|november|december)( \d{4})?$/));
-
-const isDependencyState = withRegex(/^(\d+ out of date|\d+ deprecated|up to date)$/);
-
-const isBuildStatus = Joi.equal('building', 'cancelled', 'error', 'expired', 'failed', 'failing', 'no tests',  
-                                'not built', 'not run', 'passing', 'pending', 'processing', 'queued', 'running',  
-                                'scheduled', 'skipped', 'stopped', 'success', 'timeout', 'unstable', 'waiting');
+  Joi.string().regex(
+    /^(january|february|march|april|may|june|july|august|september|october|november|december)( \d{4})?$/
+  )
+)
+
+const isDependencyState = withRegex(
+  /^(\d+ out of date|\d+ deprecated|up to date)$/
+)
+
+const isBuildStatus = Joi.equal(
+  'building',
+  'cancelled',
+  'error',
+  'expired',
+  'failed',
+  'failing',
+  'no tests',
+  'not built',
+  'not run',
+  'passing',
+  'pending',
+  'processing',
+  'queued',
+  'running',
+  'scheduled',
+  'skipped',
+  'stopped',
+  'success',
+  'timeout',
+  'unstable',
+  'waiting'
+)
 
 module.exports = {
   isSemver,
@@ -92,4 +130,4 @@ module.exports = {
   isFormattedDate,
   isDependencyState,
   isBuildStatus,
-};
+}
diff --git a/services/time/time.service.js b/services/time/time.service.js
index 2d07171660007bc396ca10b17055def6dc582e66..04f83eb50f7fd9f26a21400634954db8a1bd0736 100644
--- a/services/time/time.service.js
+++ b/services/time/time.service.js
@@ -1,11 +1,10 @@
-'use strict';
+'use strict'
 
-const { BaseService } = require('../base');
+const { BaseService } = require('../base')
 
 module.exports = class Time extends BaseService {
-
   async handle() {
-    return { message: new Date() };
+    return { message: new Date() }
   }
 
   // Metadata
@@ -13,19 +12,18 @@ module.exports = class Time extends BaseService {
     return {
       label: 'time',
       color: 'blue',
-    };
+    }
   }
 
   static get category() {
-    return 'debug';
+    return 'debug'
   }
 
   static get url() {
     return {
       base: 'servertime',
       format: '',
-      capture: []
-    };
+      capture: [],
+    }
   }
-
-};
+}
diff --git a/services/travis/travis.tester.js b/services/travis/travis.tester.js
index d7fb9b1fa2bc43e6895839e4c24b25e1abcbab4b..f8e9270a82388f0bb43e07e36bd1cc8669cb31c5 100644
--- a/services/travis/travis.tester.js
+++ b/services/travis/travis.tester.js
@@ -1,93 +1,111 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const {
-  isBuildStatus,
-  isPhpVersionReduction
-} = require('../test-validators');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { isBuildStatus, isPhpVersionReduction } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'travis', title: 'Travis CI/PHP version from .travis.yml' });
-module.exports = t;
+const t = new ServiceTester({
+  id: 'travis',
+  title: 'Travis CI/PHP version from .travis.yml',
+})
+module.exports = t
 
 // Travis CI
 
 t.create('build status on default branch')
   .get('/rust-lang/rust.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('build status on named branch')
   .get('/rust-lang/rust/stable.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('unknown repo')
   .get('/this-repo/does-not-exist.json')
-  .expectJSON({ name: 'build', value: 'unknown' });
+  .expectJSON({ name: 'build', value: 'unknown' })
 
 t.create('missing content-disposition header')
   .get('/foo/bar.json')
-  .intercept(nock => nock('https://api.travis-ci.org')
-    .head('/foo/bar.svg')
-    .reply(200))
-  .expectJSON({ name: 'build', value: 'invalid' });
+  .intercept(nock =>
+    nock('https://api.travis-ci.org')
+      .head('/foo/bar.svg')
+      .reply(200)
+  )
+  .expectJSON({ name: 'build', value: 'invalid' })
 
 t.create('connection error')
   .get('/foo/bar.json')
   .networkOff()
-  .expectJSON({ name: 'build', value: 'inaccessible' });
+  .expectJSON({ name: 'build', value: 'inaccessible' })
 
 // Travis (.com) CI
 
 t.create('build status on default branch')
   .get('/com/ivandelabeldad/rackian-gateway.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('build status on named branch')
   .get('/com/ivandelabeldad/rackian-gateway.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'build',
-    value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'build',
+      value: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
+    })
+  )
 
 t.create('unknown repo')
   .get('/com/this-repo/does-not-exist.json')
-  .expectJSON({ name: 'build', value: 'unknown' });
+  .expectJSON({ name: 'build', value: 'unknown' })
 
 t.create('missing content-disposition header')
   .get('/com/foo/bar.json')
-  .intercept(nock => nock('https://api.travis-ci.com')
-    .head('/foo/bar.svg')
-    .reply(200))
-  .expectJSON({ name: 'build', value: 'invalid' });
+  .intercept(nock =>
+    nock('https://api.travis-ci.com')
+      .head('/foo/bar.svg')
+      .reply(200)
+  )
+  .expectJSON({ name: 'build', value: 'invalid' })
 
 t.create('connection error')
   .get('/com/foo/bar.json')
   .networkOff()
-  .expectJSON({ name: 'build', value: 'inaccessible' });
+  .expectJSON({ name: 'build', value: 'inaccessible' })
 
 // PHP version from .travis.yml
 
 t.create('gets the package version of symfony')
-    .get('/php-v/symfony/symfony.json')
-    .expectJSONTypes(Joi.object().keys({ name: 'PHP', value: isPhpVersionReduction }));
+  .get('/php-v/symfony/symfony.json')
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'PHP', value: isPhpVersionReduction })
+  )
 
 t.create('gets the package version of symfony 2.8')
-    .get('/php-v/symfony/symfony/2.8.json')
-    .expectJSONTypes(Joi.object().keys({ name: 'PHP', value: isPhpVersionReduction }));
+  .get('/php-v/symfony/symfony/2.8.json')
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'PHP', value: isPhpVersionReduction })
+  )
 
 t.create('gets the package version of yii')
-    .get('/php-v/yiisoft/yii.json')
-    .expectJSONTypes(Joi.object().keys({ name: 'PHP', value: isPhpVersionReduction }));
+  .get('/php-v/yiisoft/yii.json')
+  .expectJSONTypes(
+    Joi.object().keys({ name: 'PHP', value: isPhpVersionReduction })
+  )
 
 t.create('invalid package name')
-    .get('/php-v/frodo/is-not-a-package.json')
-    .expectJSON({ name: 'PHP', value: 'invalid' });
+  .get('/php-v/frodo/is-not-a-package.json')
+  .expectJSON({ name: 'PHP', value: 'invalid' })
diff --git a/services/twitter/twitter.tester.js b/services/twitter/twitter.tester.js
index 7f66416b226490d76ea3d00a5b412cf4701b00f4..0d92607dd1723296b975c185d2d4ff25832ab8d7 100644
--- a/services/twitter/twitter.tester.js
+++ b/services/twitter/twitter.tester.js
@@ -1,41 +1,45 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const {
-  isMetric
-} = require('../test-validators');
+const { isMetric } = require('../test-validators')
 
-const t = new ServiceTester({ id: 'twitter', title: 'Twitter' });
-module.exports = t;
+const t = new ServiceTester({ id: 'twitter', title: 'Twitter' })
+module.exports = t
 
 t.create('Followers')
   .get('/follow/shields_io.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'Follow @shields_io',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'Follow @shields_io',
+      value: isMetric,
+    })
+  )
 
 t.create('Followers - Custom Label')
   .get('/follow/shields_io.json?label=Follow')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'Follow',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'Follow',
+      value: isMetric,
+    })
+  )
 
 t.create('Invalid Username Specified')
   .get('/follow/invalidusernamethatshouldnotexist.json?label=Follow')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'Follow',
-    value: 'invalid user'
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'Follow',
+      value: 'invalid user',
+    })
+  )
 
 t.create('No connection')
   .get('/follow/shields_io.json?label=Follow')
   .networkOff()
-  .expectJSON({ name: 'Follow', value: 'inaccessible' });
+  .expectJSON({ name: 'Follow', value: 'inaccessible' })
 
 t.create('URL')
   .get('/url/https/shields.io.json')
-  .expectJSON({ name: 'tweet', value: '' });
\ No newline at end of file
+  .expectJSON({ name: 'tweet', value: '' })
diff --git a/services/uptimerobot/uptimerobot.tester.js b/services/uptimerobot/uptimerobot.tester.js
index a86b53601283bb8d7c30971afade2ef475424d57..37d4563ec5e80958b0bd69e6ffe166f3f56a76df 100644
--- a/services/uptimerobot/uptimerobot.tester.js
+++ b/services/uptimerobot/uptimerobot.tester.js
@@ -1,123 +1,138 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
-const isUptimeStatus = Joi.string().regex(/^(paused|not checked yet|up|seems down|down)$/);
-const { isPercentage } = require('../test-validators');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'uptimerobot', title: 'Uptime Robot' });
-module.exports = t;
+const isUptimeStatus = Joi.string().regex(
+  /^(paused|not checked yet|up|seems down|down)$/
+)
+const { isPercentage } = require('../test-validators')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'uptimerobot', title: 'Uptime Robot' })
+module.exports = t
 
 t.create('Uptime Robot: Status (valid)')
   .get('/status/m778918918-3e92c097147760ee39d02d36.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'status',
-    value: isUptimeStatus,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'status',
+      value: isUptimeStatus,
+    })
+  )
 
 t.create('Uptime Robot: Status (invalid, correct format)')
   .get('/status/m777777777-333333333333333333333333.json')
-  .expectJSON({name: 'status', value: 'api_key not found.'});
+  .expectJSON({ name: 'status', value: 'api_key not found.' })
 
 t.create('Uptime Robot: Status (invalid, incorrect format)')
   .get('/status/not-a-service.json')
-  .expectJSON({name: 'status', value: 'must use a monitor key'});
+  .expectJSON({ name: 'status', value: 'must use a monitor key' })
 
 t.create('Uptime Robot: Status (unspecified error)')
   .get('/status/m778918918-3e92c097147760ee39d02d36.json')
-  .intercept(nock => nock('https://api.uptimerobot.com')
-    .post('/v2/getMonitors')
-    .reply(200, '{"stat": "fail"}')
+  .intercept(nock =>
+    nock('https://api.uptimerobot.com')
+      .post('/v2/getMonitors')
+      .reply(200, '{"stat": "fail"}')
   )
-  .expectJSON({name: 'status', value: 'vendor error'});
+  .expectJSON({ name: 'status', value: 'vendor error' })
 
 t.create('Uptime Robot: Status (connection error)')
   .get('/status/m778918918-3e92c097147760ee39d02d36.json')
   .networkOff()
-  .expectJSON({name: 'status', value: 'inaccessible'});
+  .expectJSON({ name: 'status', value: 'inaccessible' })
 
 t.create('Uptime Robot: Status (service unavailable)')
   .get('/status/m778918918-3e92c097147760ee39d02d36.json')
-  .intercept(nock => nock('https://api.uptimerobot.com')
-    .post('/v2/getMonitors')
-    .reply(503, '{"error": "oh noes!!"}')
+  .intercept(nock =>
+    nock('https://api.uptimerobot.com')
+      .post('/v2/getMonitors')
+      .reply(503, '{"error": "oh noes!!"}')
   )
-  .expectJSON({name: 'status', value: 'inaccessible'});
+  .expectJSON({ name: 'status', value: 'inaccessible' })
 
 t.create('Uptime Robot: Status (unexpected response, valid json)')
   .get('/status/m778918918-3e92c097147760ee39d02d36.json')
-  .intercept(nock => nock('https://api.uptimerobot.com')
-    .post('/v2/getMonitors')
-    .reply(200, "[]")
+  .intercept(nock =>
+    nock('https://api.uptimerobot.com')
+      .post('/v2/getMonitors')
+      .reply(200, '[]')
   )
-  .expectJSON({name: 'status', value: 'invalid'});
+  .expectJSON({ name: 'status', value: 'invalid' })
 
 t.create('Uptime Robot: Status (unexpected response, invalid json)')
   .get('/status/m778918918-3e92c097147760ee39d02d36.json')
-  .intercept(nock => nock('https://api.uptimerobot.com')
-    .post('/v2/getMonitors')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.uptimerobot.com')
+      .post('/v2/getMonitors')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'status', value: 'inaccessible'});
+  .expectJSON({ name: 'status', value: 'inaccessible' })
 
 t.create('Uptime Robot: Percentage (valid)')
   .get('/ratio/m778918918-3e92c097147760ee39d02d36.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'uptime',
-    value: isPercentage,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'uptime',
+      value: isPercentage,
+    })
+  )
 
 t.create('Uptime Robot: Percentage (valid, with numberOfDays param)')
   .get('/ratio/7/m778918918-3e92c097147760ee39d02d36.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'uptime',
-    value: isPercentage,
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'uptime',
+      value: isPercentage,
+    })
+  )
 
 t.create('Uptime Robot: Percentage (invalid, correct format)')
   .get('/ratio/m777777777-333333333333333333333333.json')
-  .expectJSON({name: 'uptime', value: 'api_key not found.'});
+  .expectJSON({ name: 'uptime', value: 'api_key not found.' })
 
 t.create('Uptime Robot: Percentage (invalid, incorrect format)')
   .get('/ratio/not-a-service.json')
-  .expectJSON({name: 'uptime', value: 'must use a monitor key'});
+  .expectJSON({ name: 'uptime', value: 'must use a monitor key' })
 
 t.create('Uptime Robot: Percentage (unspecified error)')
   .get('/ratio/m778918918-3e92c097147760ee39d02d36.json')
-  .intercept(nock => nock('https://api.uptimerobot.com')
-    .post('/v2/getMonitors')
-    .reply(200, '{"stat": "fail"}')
+  .intercept(nock =>
+    nock('https://api.uptimerobot.com')
+      .post('/v2/getMonitors')
+      .reply(200, '{"stat": "fail"}')
   )
-  .expectJSON({name: 'uptime', value: 'vendor error'});
+  .expectJSON({ name: 'uptime', value: 'vendor error' })
 
 t.create('Uptime Robot: Percentage (connection error)')
   .get('/ratio/m778918918-3e92c097147760ee39d02d36.json')
   .networkOff()
-  .expectJSON({name: 'uptime', value: 'inaccessible'});
+  .expectJSON({ name: 'uptime', value: 'inaccessible' })
 
 t.create('Uptime Robot: Percentage (service unavailable)')
   .get('/ratio/m778918918-3e92c097147760ee39d02d36.json')
-  .intercept(nock => nock('https://api.uptimerobot.com')
-    .post('/v2/getMonitors')
-    .reply(503, '{"error": "oh noes!!"}')
+  .intercept(nock =>
+    nock('https://api.uptimerobot.com')
+      .post('/v2/getMonitors')
+      .reply(503, '{"error": "oh noes!!"}')
   )
-  .expectJSON({name: 'uptime', value: 'inaccessible'});
+  .expectJSON({ name: 'uptime', value: 'inaccessible' })
 
 t.create('Uptime Robot: Percentage (unexpected response, valid json)')
   .get('/ratio/m778918918-3e92c097147760ee39d02d36.json')
-  .intercept(nock => nock('https://api.uptimerobot.com')
-    .post('/v2/getMonitors')
-    .reply(200, "[]")
+  .intercept(nock =>
+    nock('https://api.uptimerobot.com')
+      .post('/v2/getMonitors')
+      .reply(200, '[]')
   )
-  .expectJSON({name: 'uptime', value: 'invalid'});
+  .expectJSON({ name: 'uptime', value: 'invalid' })
 
 t.create('Uptime Robot: Percentage (unexpected response, invalid json)')
   .get('/ratio/m778918918-3e92c097147760ee39d02d36.json')
-  .intercept(nock => nock('https://api.uptimerobot.com')
-    .post('/v2/getMonitors')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.uptimerobot.com')
+      .post('/v2/getMonitors')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'uptime', value: 'inaccessible'});
+  .expectJSON({ name: 'uptime', value: 'inaccessible' })
diff --git a/services/vaadin-directory/vaadin-directory.tester.js b/services/vaadin-directory/vaadin-directory.tester.js
index 8f2616686bfa160fd6c09e3846d922a90e316e50..cd970d04f0db59bc94cf26ea81de88bcb48ec952 100644
--- a/services/vaadin-directory/vaadin-directory.tester.js
+++ b/services/vaadin-directory/vaadin-directory.tester.js
@@ -1,102 +1,129 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 
 // Get validate function from validator.js lib
 const {
   isSemver,
   isStarRating,
-  isFormattedDate
-} = require('../test-validators');
+  isFormattedDate,
+} = require('../test-validators')
 
 const t = new ServiceTester({
   id: 'vaadin-directory',
-  title: 'Vaadin Directory'
-});
-module.exports = t;
+  title: 'Vaadin Directory',
+})
+module.exports = t
 
 t.create('stars of component displayed in star icons')
   .get('/star/vaadinvaadin-grid.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'stars',
-    value: isStarRating
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'stars',
+      value: isStarRating,
+    })
+  )
 
 t.create('stars of component displayed in star icons')
   .get('/stars/vaadinvaadin-grid.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'stars',
-    value: isStarRating
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'stars',
+      value: isStarRating,
+    })
+  )
 
 t.create('publish status of the component')
   .get('/status/vaadinvaadin-grid.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'Vaadin Directory',
-    value: Joi.equal('published', 'unpublished', 'incomplete', 'reported', 'suspended', 'deleted')
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'Vaadin Directory',
+      value: Joi.equal(
+        'published',
+        'unpublished',
+        'incomplete',
+        'reported',
+        'suspended',
+        'deleted'
+      ),
+    })
+  )
 
 t.create('rating of the compoennt (eg: 4.2/5)')
   .get('/rating/vaadinvaadin-grid.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'rating',
-    value: Joi.string().regex(/^\d\.\d\/5$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rating',
+      value: Joi.string().regex(/^\d\.\d\/5$/),
+    })
+  )
 
 t.create('rating count of component')
   .get('/rc/vaadinvaadin-grid.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'rating count',
-    value: Joi.string().regex(/^\d+?\stotal$/)
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rating count',
+      value: Joi.string().regex(/^\d+?\stotal$/),
+    })
+  )
 
-  t.create('rating count of component')
-    .get('/rating-count/vaadinvaadin-grid.json')
-    .expectJSONTypes(Joi.object().keys({
+t.create('rating count of component')
+  .get('/rating-count/vaadinvaadin-grid.json')
+  .expectJSONTypes(
+    Joi.object().keys({
       name: 'rating count',
-      value: Joi.string().regex(/^\d+?\stotal$/)
-    }));
+      value: Joi.string().regex(/^\d+?\stotal$/),
+    })
+  )
 
 t.create('latest version of the component (can have v prefixed or without)')
   .get('/v/vaadinvaadin-grid.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'latest ver',
-    value: isSemver
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'latest ver',
+      value: isSemver,
+    })
+  )
 
-  t.create('latest version of the component (can have v prefixed or without)')
-    .get('/version/vaadinvaadin-grid.json')
-    .expectJSONTypes(Joi.object().keys({
+t.create('latest version of the component (can have v prefixed or without)')
+  .get('/version/vaadinvaadin-grid.json')
+  .expectJSONTypes(
+    Joi.object().keys({
       name: 'latest ver',
-      value: isSemver
-    }));
+      value: isSemver,
+    })
+  )
 
 t.create('latest release date of the component (format: yyyy-mm-dd)')
   .get('/rd/vaadinvaadin-grid.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'latest release date',
-    value: isFormattedDate
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'latest release date',
+      value: isFormattedDate,
+    })
+  )
 
-  t.create('latest release date of the component (format: yyyy-mm-dd)')
-    .get('/release-date/vaadinvaadin-grid.json')
-    .expectJSONTypes(Joi.object().keys({
+t.create('latest release date of the component (format: yyyy-mm-dd)')
+  .get('/release-date/vaadinvaadin-grid.json')
+  .expectJSONTypes(
+    Joi.object().keys({
       name: 'latest release date',
-      value: isFormattedDate
-    }));
+      value: isFormattedDate,
+    })
+  )
 
 t.create('Invalid addon')
   .get('/stars/404.json')
   .expectJSON({
     name: 'Vaadin Directory',
-    value: 'not found'
-  });
+    value: 'not found',
+  })
 
 t.create('No connection')
   .get('/stars/vaadinvaadin-grid.json')
   .networkOff()
   .expectJSON({
     name: 'Vaadin Directory',
-    value: 'inaccessible'
-  });
+    value: 'inaccessible',
+  })
diff --git a/services/vscode-marketplace/vscode-marketplace.tester.js b/services/vscode-marketplace/vscode-marketplace.tester.js
index 36a246ad6ff76f8f78861a276e6d4f59456017f9..58054cfa60920e7b95f53002c7285caf34f8021f 100644
--- a/services/vscode-marketplace/vscode-marketplace.tester.js
+++ b/services/vscode-marketplace/vscode-marketplace.tester.js
@@ -1,70 +1,89 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isVPlusTripleDottedVersion,
   isMetric,
-  isStarRating
-} = require('../test-validators');
+  isStarRating,
+} = require('../test-validators')
 
-const isVscodeRating = Joi.string().regex(/[0-5].[0-9]{2}\/5?\s*\([0-9]*\)$/);
+const isVscodeRating = Joi.string().regex(/[0-5].[0-9]{2}\/5?\s*\([0-9]*\)$/)
 
-const t = new ServiceTester({ id: 'vscode-marketplace', title: 'VS Code Marketplace' });
-module.exports = t;
+const t = new ServiceTester({
+  id: 'vscode-marketplace',
+  title: 'VS Code Marketplace',
+})
+module.exports = t
 
 t.create('Downloads')
   .get('/d/ritwickdey.LiveServer.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'downloads',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('Downloads | User specified label')
   .get('/d/ritwickdey.LiveServer.json?label=Total Installs')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'Total Installs',
-    value: isMetric
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'Total Installs',
+      value: isMetric,
+    })
+  )
 
 t.create('Rating')
   .get('/r/ritwickdey.LiveServer.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'rating',
-    value: isVscodeRating
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rating',
+      value: isVscodeRating,
+    })
+  )
 
 t.create('Rating | User specified label')
   .get('/r/ritwickdey.LiveServer.json?label=My custom rating label')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'My custom rating label',
-    value: isVscodeRating
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'My custom rating label',
+      value: isVscodeRating,
+    })
+  )
 
 t.create('Star Rating')
   .get('/stars/ritwickdey.LiveServer.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'rating',
-    value: isStarRating
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rating',
+      value: isStarRating,
+    })
+  )
 
 t.create('Star Rating | User specified label')
   .get('/stars/ritwickdey.LiveServer.json?label=My custom rating label')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'My custom rating label',
-    value: isStarRating
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'My custom rating label',
+      value: isStarRating,
+    })
+  )
 
 t.create('Version')
   .get('/v/ritwickdey.LiveServer.json')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'visual studio marketplace',
-    value: isVPlusTripleDottedVersion
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'visual studio marketplace',
+      value: isVPlusTripleDottedVersion,
+    })
+  )
 
 t.create('Version | User specified label')
   .get('/v/ritwickdey.LiveServer.json?label=VSM')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'VSM',
-    value: isVPlusTripleDottedVersion
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'VSM',
+      value: isVPlusTripleDottedVersion,
+    })
+  )
diff --git a/services/waffle/waffle.tester.js b/services/waffle/waffle.tester.js
index 0fc5d735b61364c0bfee4430b182ef43c22c0800..f1431f0a89d0761c1814c20e1a97bf480440632c 100644
--- a/services/waffle/waffle.tester.js
+++ b/services/waffle/waffle.tester.js
@@ -1,90 +1,101 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
-const { invalidJSON } = require('../response-fixtures');
-
-const t = new ServiceTester({ id: 'waffle', title: 'Waffle.io' });
-module.exports = t;
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
+const { invalidJSON } = require('../response-fixtures')
 
+const t = new ServiceTester({ id: 'waffle', title: 'Waffle.io' })
+module.exports = t
 
 const fakeData = [
   {
-    "label": null,
-    "count": 20
+    label: null,
+    count: 20,
   },
   {
-    "count": 10
+    count: 10,
   },
   {
-    "label": {
-      "color": "c5def5",
-      "name": "feature"
+    label: {
+      color: 'c5def5',
+      name: 'feature',
     },
-    "count": 3
+    count: 3,
   },
   {
-    "label": {
-      "name": "bug",
-      "color": "fbca04"
+    label: {
+      name: 'bug',
+      color: 'fbca04',
     },
-    "count": 5
-  }
-];
-
+    count: 5,
+  },
+]
 
-t.create('label should be `bug` & value should be exactly 5 as supplied in `fakeData`.  e.g: bug|5')
+t.create(
+  'label should be `bug` & value should be exactly 5 as supplied in `fakeData`.  e.g: bug|5'
+)
   .get('/label/userName/repoName/bug.json?style=_shields_test')
-  .intercept(nock => nock('https://api.waffle.io/')
-    .get('/userName/repoName/columns?with=count')
-    .reply(200, fakeData))
+  .intercept(nock =>
+    nock('https://api.waffle.io/')
+      .get('/userName/repoName/columns?with=count')
+      .reply(200, fakeData)
+  )
   .expectJSON({
     name: 'bug',
     value: '5',
     colorB: '#fbca04',
-  });
+  })
 
 t.create('label should be `Mybug` & value should be formated.  e.g: Mybug|25')
   .get('/label/ritwickdey/vscode-live-server/bug.json?label=Mybug')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'Mybug',
-    value: Joi.number().integer().positive()
-  }));
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'Mybug',
+      value: Joi.number()
+        .integer()
+        .positive(),
+    })
+  )
 
 t.create('label (repo not found)')
   .get('/label/not-a-user/not-a-repo/bug.json')
   .expectJSON({
     name: 'waffle',
     value: 'not found',
-  });
+  })
 
 t.create('label (label not found)')
-  .get('/label/ritwickdey/vscode-live-server/not-a-real-label.json?style=_shields_test')
+  .get(
+    '/label/ritwickdey/vscode-live-server/not-a-real-label.json?style=_shields_test'
+  )
   .expectJSON({
     name: 'not-a-real-label',
     value: '0',
     colorB: '#78bdf2',
-  });
+  })
 
 t.create('label (empty response)')
   .get('/label/userName/repoName/bug.json')
-  .intercept(nock => nock('https://api.waffle.io/')
-    .get('/userName/repoName/columns?with=count')
-    .reply(200, []))
+  .intercept(nock =>
+    nock('https://api.waffle.io/')
+      .get('/userName/repoName/columns?with=count')
+      .reply(200, [])
+  )
   .expectJSON({
     name: 'waffle',
     value: 'absent',
-  });
+  })
 
 t.create('label (connection error)')
   .get('/label/ritwickdey/vscode-live-server/bug.json')
   .networkOff()
-  .expectJSON({name: 'waffle', value: 'inaccessible'});
+  .expectJSON({ name: 'waffle', value: 'inaccessible' })
 
 t.create('label (unexpected response)')
   .get('/label/userName/repoName/bug.json')
-  .intercept(nock => nock('https://api.waffle.io/')
-    .get('/userName/repoName/columns?with=count')
-    .reply(invalidJSON)
+  .intercept(nock =>
+    nock('https://api.waffle.io/')
+      .get('/userName/repoName/columns?with=count')
+      .reply(invalidJSON)
   )
-  .expectJSON({name: 'waffle', value: 'invalid'});
+  .expectJSON({ name: 'waffle', value: 'invalid' })
diff --git a/services/website/website.tester.js b/services/website/website.tester.js
index ee1db11f5c6bc0b82efa0968fb16ce68cdae367d..8809436848161899ed0a9db04e3bee0976fc965f 100644
--- a/services/website/website.tester.js
+++ b/services/website/website.tester.js
@@ -1,40 +1,46 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
-const colorscheme = require('../../lib/colorscheme.json');
-const mapValues = require('lodash.mapvalues');
+const ServiceTester = require('../service-tester')
+const colorscheme = require('../../lib/colorscheme.json')
+const mapValues = require('lodash.mapvalues')
 
-const t = new ServiceTester({ id: 'website', title: 'website' });
-module.exports = t;
-const colorsB = mapValues(colorscheme, 'colorB');
+const t = new ServiceTester({ id: 'website', title: 'website' })
+module.exports = t
+const colorsB = mapValues(colorscheme, 'colorB')
 
 t.create('status of http://shields.io')
   .get('/http/shields.io.json?style=_shields_test')
-  .expectJSON({ name: 'website', value: 'online', colorB: colorsB.brightgreen });
+  .expectJSON({ name: 'website', value: 'online', colorB: colorsB.brightgreen })
 
 t.create('status of https://shields.io')
   .get('/https/shields.io.json?style=_shields_test')
-  .expectJSON({ name: 'website', value: 'online', colorB: colorsB.brightgreen });
+  .expectJSON({ name: 'website', value: 'online', colorB: colorsB.brightgreen })
 
 t.create('status of nonexistent domain')
   .get('/https/shields-io.io.json?style=_shields_test')
-  .expectJSON({ name: 'website', value: 'offline', colorB: colorsB.red });
+  .expectJSON({ name: 'website', value: 'offline', colorB: colorsB.red })
 
 t.create('status when network is off')
   .get('/http/shields.io.json?style=_shields_test')
   .networkOff()
-  .expectJSON({ name: 'website', value: 'offline', colorB: colorsB.red });
+  .expectJSON({ name: 'website', value: 'offline', colorB: colorsB.red })
 
 t.create('custom online label, online message and online color')
-  .get('-up-down-green-grey/http/online.com.json?style=_shields_test&label=homepage')
-  .intercept(nock => nock('http://online.com')
-    .head('/')
-    .reply(200))
-  .expectJSON({ name: 'homepage', value: 'up', colorB: colorsB.green });
+  .get(
+    '-up-down-green-grey/http/online.com.json?style=_shields_test&label=homepage'
+  )
+  .intercept(nock =>
+    nock('http://online.com')
+      .head('/')
+      .reply(200)
+  )
+  .expectJSON({ name: 'homepage', value: 'up', colorB: colorsB.green })
 
 t.create('custom offline message and offline color')
   .get('-up-down-green-grey/http/offline.com.json?style=_shields_test')
-  .intercept(nock => nock('http://offline.com')
-    .head('/')
-    .reply(500))
-  .expectJSON({ name: 'website', value: 'down', colorB: colorsB.grey });
+  .intercept(nock =>
+    nock('http://offline.com')
+      .head('/')
+      .reply(500)
+  )
+  .expectJSON({ name: 'website', value: 'down', colorB: colorsB.grey })
diff --git a/services/wordpress/wordpress.tester.js b/services/wordpress/wordpress.tester.js
index ef6abfc567ae1af11f8323c9c87d0be7771f591e..175bb1fe8c624b21cc405a8c69397f1da1057682 100644
--- a/services/wordpress/wordpress.tester.js
+++ b/services/wordpress/wordpress.tester.js
@@ -1,54 +1,66 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const ServiceTester = require('../service-tester');
+const Joi = require('joi')
+const ServiceTester = require('../service-tester')
 const {
   isMetric,
   isStarRating,
-  isVPlusDottedVersionAtLeastOne
-} = require('../test-validators');
+  isVPlusDottedVersionAtLeastOne,
+} = require('../test-validators')
 
-const t = new ServiceTester({ id: 'wordpress', title: 'Wordpress' });
-module.exports = t;
+const t = new ServiceTester({ id: 'wordpress', title: 'Wordpress' })
+module.exports = t
 
 t.create('supported version')
-.get('/v/akismet.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'wordpress',
-  value: Joi.string().regex(/^\d+(\.\d+)?(\.\d+)? tested$/)
-}));
+  .get('/v/akismet.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'wordpress',
+      value: Joi.string().regex(/^\d+(\.\d+)?(\.\d+)? tested$/),
+    })
+  )
 
 t.create('plugin version')
-.get('/plugin/v/akismet.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'plugin',
-  value: isVPlusDottedVersionAtLeastOne
-}));
+  .get('/plugin/v/akismet.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'plugin',
+      value: isVPlusDottedVersionAtLeastOne,
+    })
+  )
 
 t.create('plugin rating')
-.get('/plugin/r/akismet.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'rating',
-  value: isStarRating
-}));
+  .get('/plugin/r/akismet.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rating',
+      value: isStarRating,
+    })
+  )
 
 t.create('plugin downloads')
-.get('/plugin/dt/akismet.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'downloads',
-  value: isMetric
-}));
+  .get('/plugin/dt/akismet.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
 
 t.create('theme rating')
-.get('/theme/r/hestia.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'rating',
-  value: isStarRating
-}));
+  .get('/theme/r/hestia.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'rating',
+      value: isStarRating,
+    })
+  )
 
 t.create('theme downloads')
-.get('/theme/dt/hestia.json')
-.expectJSONTypes(Joi.object().keys({
-  name: 'downloads',
-  value: isMetric
-}));
+  .get('/theme/dt/hestia.json')
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'downloads',
+      value: isMetric,
+    })
+  )
diff --git a/services/xml/xml.tester.js b/services/xml/xml.tester.js
index 429fd25ebfb7f72393e67b54a3713edc7848f774..9d00ea8ada56c37741713fa239149b8cb8290cdd 100644
--- a/services/xml/xml.tester.js
+++ b/services/xml/xml.tester.js
@@ -1,104 +1,187 @@
-'use strict';
+'use strict'
 
-const Joi = require('joi');
-const { expect } = require('chai');
-const ServiceTester = require('../service-tester');
-const {
-  isSemver,
-} = require('../test-validators');
+const Joi = require('joi')
+const { expect } = require('chai')
+const ServiceTester = require('../service-tester')
+const { isSemver } = require('../test-validators')
 
-const colorscheme = require('../../lib/colorscheme.json');
-const mapValues = require('lodash.mapvalues');
+const colorscheme = require('../../lib/colorscheme.json')
+const mapValues = require('lodash.mapvalues')
 
-const colorsB = mapValues(colorscheme, 'colorB');
+const colorsB = mapValues(colorscheme, 'colorB')
 
-const t = new ServiceTester({ id: 'dynamic-xml', title: 'User Defined XML Source Data', pathPrefix: '/badge/dynamic/xml' });
-module.exports = t;
+const t = new ServiceTester({
+  id: 'dynamic-xml',
+  title: 'User Defined XML Source Data',
+  pathPrefix: '/badge/dynamic/xml',
+})
+module.exports = t
 
 t.create('Connection error')
-  .get('.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name&label=Package Name&style=_shields_test')
+  .get(
+    '.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name&label=Package Name&style=_shields_test'
+  )
   .networkOff()
-  .expectJSON({ name: 'Package Name', value: 'inaccessible', colorB: colorsB.red });
+  .expectJSON({
+    name: 'Package Name',
+    value: 'inaccessible',
+    colorB: colorsB.red,
+  })
 
 t.create('No URL specified')
   .get('.json?query=//name&label=Package Name&style=_shields_test')
-  .expectJSON({ name: 'Package Name', value: 'no url specified', colorB: colorsB.red });
+  .expectJSON({
+    name: 'Package Name',
+    value: 'no url specified',
+    colorB: colorsB.red,
+  })
 
 t.create('No query specified')
-  .get('.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&label=Package Name&style=_shields_test')
-  .expectJSON({ name: 'Package Name', value: 'no query specified', colorB: colorsB.red });
+  .get(
+    '.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&label=Package Name&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'Package Name',
+    value: 'no query specified',
+    colorB: colorsB.red,
+  })
 
 t.create('XML from url')
-  .get('.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'IndieGala Helper', colorB: colorsB.brightgreen });
+  .get(
+    '.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'IndieGala Helper',
+    colorB: colorsB.brightgreen,
+  })
 
 t.create('XML from uri (support uri query paramater)')
-  .get('.json?uri=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'IndieGala Helper', colorB: colorsB.brightgreen });
+  .get(
+    '.json?uri=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'IndieGala Helper',
+    colorB: colorsB.brightgreen,
+  })
 
 t.create('XML from url (attribute)')
-  .get('.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/reviews/@num')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'custom badge',
-    value: Joi.string().regex(/^\d+$/)
-  }));
+  .get(
+    '.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/reviews/@num'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'custom badge',
+      value: Joi.string().regex(/^\d+$/),
+    })
+  )
 
 t.create('XML from url | multiple results')
-  .get('.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/compatible_applications/application/name')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'custom badge',
-    value: Joi.string().regex(/^Firefox( for Android)?,\sFirefox( for Android)?$/)
-  }));
+  .get(
+    '.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/compatible_applications/application/name'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'custom badge',
+      value: Joi.string().regex(
+        /^Firefox( for Android)?,\sFirefox( for Android)?$/
+      ),
+    })
+  )
 
 t.create('XML from url | caching with new query params')
-  .get('.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/version')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'custom badge',
-    value: isSemver
-  }));
+  .get(
+    '.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/version'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'custom badge',
+      value: isSemver,
+    })
+  )
 
 t.create('XML from url | with prefix & suffix & label')
-  .get('.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=//version&prefix=v&suffix= dev&label=IndieGala Helper')
-  .expectJSONTypes(Joi.object().keys({
-    name: 'IndieGala Helper',
-    value: Joi.string().regex(/^v\d+(\.\d+)?(\.\d+)?\sdev$/)
-  }));
+  .get(
+    '.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=//version&prefix=v&suffix= dev&label=IndieGala Helper'
+  )
+  .expectJSONTypes(
+    Joi.object().keys({
+      name: 'IndieGala Helper',
+      value: Joi.string().regex(/^v\d+(\.\d+)?(\.\d+)?\sdev$/),
+    })
+  )
 
 t.create('XML from url | query doesnt exist')
-  .get('.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/does/not/exist&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'no result', colorB: colorsB.lightgrey });
+  .get(
+    '.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/does/not/exist&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'no result',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('XML from url | query doesnt exist (attribute)')
-  .get('.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/does/not/@exist&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'no result', colorB: colorsB.lightgrey });
+  .get(
+    '.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/does/not/@exist&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'no result',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('XML from url | invalid url')
-  .get('.json?url=https://github.com/badges/shields/raw/master/notafile.xml&query=//version&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'resource not found', colorB: colorsB.lightgrey });
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/notafile.xml&query=//version&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'resource not found',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('XML from url | user color overrides default')
-  .get('.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name&colorB=10ADED&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'IndieGala Helper', colorB: '#10ADED' });
+  .get(
+    '.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name&colorB=10ADED&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'IndieGala Helper',
+    colorB: '#10ADED',
+  })
 
 t.create('XML from url | error color overrides default')
-  .get('.json?url=https://github.com/badges/shields/raw/master/notafile.xml&query=//version&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'resource not found', colorB: colorsB.lightgrey });
+  .get(
+    '.json?url=https://github.com/badges/shields/raw/master/notafile.xml&query=//version&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'resource not found',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('XML from url | error color overrides user specified')
   .get('.json?query=//version&colorB=10ADED&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'no url specified', colorB: colorsB.red });
+  .expectJSON({
+    name: 'custom badge',
+    value: 'no url specified',
+    colorB: colorsB.red,
+  })
 
-let headers;
+let headers
 t.create('XML from url | request should set Accept header')
   .get('.json?url=https://xml-test/api.xml&query=/name')
-  .intercept(nock => nock('https://xml-test')
-    .get('/api.xml')
-    .reply(200, function (uri, requestBody) {
-      headers = this.req.headers;
-      return '<?xml version="1.0" encoding="utf-8" ?><name>dynamic xml</name>';
-    })
+  .intercept(nock =>
+    nock('https://xml-test')
+      .get('/api.xml')
+      .reply(200, function(uri, requestBody) {
+        headers = this.req.headers
+        return '<?xml version="1.0" encoding="utf-8" ?><name>dynamic xml</name>'
+      })
   )
   .expectJSON({ name: 'custom badge', value: 'dynamic xml' })
-  .after(function () {
-    expect(headers).to.have.property('accept', 'application/xml, text/xml');
-  });
+  .after(function() {
+    expect(headers).to.have.property('accept', 'application/xml, text/xml')
+  })
diff --git a/services/yaml/yaml.tester.js b/services/yaml/yaml.tester.js
index 8606c4f34a3cb4c8ec751e4de9e02ef6fa7714f3..fff75272a22ab506f77d430732cff57a89381e63 100644
--- a/services/yaml/yaml.tester.js
+++ b/services/yaml/yaml.tester.js
@@ -1,63 +1,125 @@
-'use strict';
+'use strict'
 
-const ServiceTester = require('../service-tester');
-const colorscheme = require('../../lib/colorscheme.json');
-const mapValues = require('lodash.mapvalues');
+const ServiceTester = require('../service-tester')
+const colorscheme = require('../../lib/colorscheme.json')
+const mapValues = require('lodash.mapvalues')
 
-const colorsB = mapValues(colorscheme, 'colorB');
+const colorsB = mapValues(colorscheme, 'colorB')
 
-const t = new ServiceTester({ id: 'dynamic-yaml', title: 'User Defined YAML Source Data', pathPrefix: '/badge/dynamic/yaml' });
-module.exports = t;
+const t = new ServiceTester({
+  id: 'dynamic-yaml',
+  title: 'User Defined YAML Source Data',
+  pathPrefix: '/badge/dynamic/yaml',
+})
+module.exports = t
 
 t.create('Connection error')
-  .get('.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.name&label=Package Name&style=_shields_test')
+  .get(
+    '.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.name&label=Package Name&style=_shields_test'
+  )
   .networkOff()
-  .expectJSON({ name: 'Package Name', value: 'inaccessible', colorB: colorsB.red });
+  .expectJSON({
+    name: 'Package Name',
+    value: 'inaccessible',
+    colorB: colorsB.red,
+  })
 
 t.create('No URL specified')
   .get('.json?query=$.name&label=Package Name&style=_shields_test')
-  .expectJSON({ name: 'Package Name', value: 'no url specified', colorB: colorsB.red });
+  .expectJSON({
+    name: 'Package Name',
+    value: 'no url specified',
+    colorB: colorsB.red,
+  })
 
 t.create('No query specified')
-  .get('.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&label=Package Name&style=_shields_test')
-  .expectJSON({ name: 'Package Name', value: 'no query specified', colorB: colorsB.red });
+  .get(
+    '.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&label=Package Name&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'Package Name',
+    value: 'no query specified',
+    colorB: colorsB.red,
+  })
 
 t.create('YAML from url')
-  .get('.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.name&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'coredns', colorB: colorsB.brightgreen });
+  .get(
+    '.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.name&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'coredns',
+    colorB: colorsB.brightgreen,
+  })
 
 t.create('YAML from uri (support uri query paramater)')
-  .get('.json?uri=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.name&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'coredns', colorB: colorsB.brightgreen });
+  .get(
+    '.json?uri=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.name&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'coredns',
+    colorB: colorsB.brightgreen,
+  })
 
 t.create('YAML from url | multiple results')
-  .get('.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$..keywords[0:2:1]')
-  .expectJSON({ name: 'custom badge', value: 'coredns, dns' });
+  .get(
+    '.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$..keywords[0:2:1]'
+  )
+  .expectJSON({ name: 'custom badge', value: 'coredns, dns' })
 
 t.create('YAML from url | caching with new query params')
-  .get('.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.version')
-  .expectJSON({ name: 'custom badge', value: '0.8.0' });
+  .get(
+    '.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.version'
+  )
+  .expectJSON({ name: 'custom badge', value: '0.8.0' })
 
 t.create('YAML from url | with prefix & suffix & label')
-  .get('.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.version&prefix=v&suffix= dev&label=Shields')
-  .expectJSON({ name: 'Shields', value: 'v0.8.0 dev' });
+  .get(
+    '.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.version&prefix=v&suffix= dev&label=Shields'
+  )
+  .expectJSON({ name: 'Shields', value: 'v0.8.0 dev' })
 
 t.create('YAML from url | object doesnt exist')
-  .get('.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.does_not_exist&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'no result', colorB: colorsB.lightgrey });
+  .get(
+    '.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.does_not_exist&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'no result',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('YAML from url | invalid url')
-  .get('.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/notafile.yaml&query=$.version&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'resource not found', colorB: colorsB.lightgrey });
+  .get(
+    '.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/notafile.yaml&query=$.version&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'resource not found',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('YAML from url | user color overrides default')
-  .get('.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.name&colorB=10ADED&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'coredns', colorB: '#10ADED' });
+  .get(
+    '.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/Chart.yaml&query=$.name&colorB=10ADED&style=_shields_test'
+  )
+  .expectJSON({ name: 'custom badge', value: 'coredns', colorB: '#10ADED' })
 
 t.create('YAML from url | error color overrides default')
-  .get('.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/notafile.yaml&query=$.version&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'resource not found', colorB: colorsB.lightgrey });
+  .get(
+    '.json?url=https://raw.githubusercontent.com/kubernetes/charts/568291d6e476c39ca8322c30c3f601d0383d4760/stable/coredns/notafile.yaml&query=$.version&style=_shields_test'
+  )
+  .expectJSON({
+    name: 'custom badge',
+    value: 'resource not found',
+    colorB: colorsB.lightgrey,
+  })
 
 t.create('YAML from url | error color overrides user specified')
   .get('.json?query=$.version&colorB=10ADED&style=_shields_test')
-  .expectJSON({ name: 'custom badge', value: 'no url specified', colorB: colorsB.red });
+  .expectJSON({
+    name: 'custom badge',
+    value: 'no url specified',
+    colorB: colorsB.red,
+  })