diff --git a/bin/paged b/bin/paged
index d6b22bb8dfc00c52ba0ca35cf5d703129343bf0e..71a10a2c44abb88ff3ca602e7613ec2228cde6e2 100755
--- a/bin/paged
+++ b/bin/paged
@@ -1,5 +1,6 @@
 #!/usr/bin/env node
 const program = require('commander');
+const ora = require('ora');
 const Printer = require("../");
 const path = require('path');
 const fs = require('fs');
@@ -24,13 +25,25 @@ program
   // .option('-e, --encoding [type]', 'Set the encoding of the input html, defaults to "utf-8"')
   .option('-t, --timeout [ms]', 'Set a max timeout of [ms]')
   .option('-x, --html', 'output html file')
+  .option('-b, --blockLocal', 'Disallow access to filesystem for local files')
   .parse(process.argv);
 
 
 let input = program.inputs || program.args[0];
 
 let dir = process.cwd();
-let relativePath = path.resolve(dir, input);
+
+let url;
+let relativePath;
+let allowLocal;
+try {
+  url = new URL(input);
+  allowLocal = false;
+} catch {
+  relativePath = path.resolve(dir, input);
+  allowLocal = !program.blockLocal;
+}
+
 let output;
 let tmpFile, tmpPath;
 
@@ -44,16 +57,19 @@ if (!input) {
   return process.exit(1);
 }
 
-if (['.html', '.xhtml'].indexOf(path.extname(relativePath)) === -1) {
-  console.error("Must pass a html or xhtml file as input");
-  return process.exit(1);
-}
+if (relativePath) {
 
-try {
-    fs.accessSync(relativePath, fs.F_OK);
-} catch (e) {
-    console.error("Input cannot be found", e);
+  if (['.html', '.xhtml'].indexOf(path.extname(relativePath)) === -1) {
+    console.error("Must pass a html or xhtml file as input");
     return process.exit(1);
+  }
+
+  try {
+      fs.accessSync(relativePath, fs.F_OK);
+  } catch (e) {
+      console.error("Input cannot be found", e);
+      return process.exit(1);
+  }
 }
 
 if (typeof(program.output) === "string") {
@@ -64,34 +80,40 @@ if (typeof(program.output) === "string") {
   output = "output.pdf";
 }
 
-/*
-if (program.hyphenate) {
-  hyphenateOptions = {
-    ignore: program.hypher_ignore || undefined,
-    only: program.hypher_only || undefined,
-    encoding: program.encoding || undefined
-  }
 
-  tmpPath = replaceExt(relativePath, ".hyphenated.html");
+const spinner = ora({
+  spinner: "circleQuarters"
+})
 
-  // tmpFile = temp.openSync({suffix: '.html'});
-  // tmpPath = tmpFile.path;
-  // Create a new Hyphenator, with passed language
-  hyphenator = new Hyphenator(program.hyphenate);
-  hyphenator.process(relativePath, tmpPath, hyphenateOptions);
 
-  console.log("Hyphenated for", typeof(program.hyphenate) === "string" ? program.hyphenate : "en-us");
+if (typeof input === "string") {
+  spinner.start("Loading: " + input);
+} else {
+  spinner.start("Loading");
+}
 
-  if (program.debug && tmpPath) {
-    console.log("Hyphenated file at:", tmpPath);
-  }
+(async () => {
+  let printer = new Printer(headless, allowLocal);
 
-}
-*/
+  printer.on("page", (page) => {
+    if (page.position === 0) {
+      spinner.succeed("Loaded");
 
+      spinner.start("Rendering: Page " + (page.position + 1));
+    } else {
+      spinner.text = "Rendering: Page " + (page.position + 1)
+    }
+  });
 
-(async () => {
-  let printer = new Printer(headless);
+  printer.on("rendered", (msg) => {
+    spinner.succeed(msg);
+    spinner.start("Generating");
+  });
+
+  printer.on("postprocessing", (msg) => {
+    spinner.succeed("Generated");
+    spinner.start("Processing");
+  });
 
   let file;
   if (headless) {
@@ -106,10 +128,12 @@ if (program.hyphenate) {
     printer.preview(input);
   }
 
+  spinner.succeed("Processed");
+
   if (file) {
     fs.writeFile(output, file, (err) => {
       if (err) throw err;
-      console.log('Saved to', output);
+      spinner.succeed("Saved to " + output);
       process.exit(0);
     });
   }
diff --git a/index.js b/index.js
index a494cd38d02e47138325b955fc00d07402369f84..a0e4b754d6e47a886d4985ca2fbe3de5e17b3646 100644
--- a/index.js
+++ b/index.js
@@ -1,154 +1,3 @@
-const Paged = require('pagedjs');
-const EventEmitter = require('events');
-const puppeteer = require('puppeteer');
-
-// const temp = require("temp").track();
-const path = require('path');
-const fs = require('fs');
-
-const express = require('express');
-const app = express();
-
-const PORT = 9999;
-
-let dir = process.cwd();
-
-let scriptPath = path.resolve(dir, "./node_modules/pagedjs/dist/");
-
-const PDF_SETTINGS = {
-  printBackground: true,
-  displayHeaderFooter: false,
-  preferCSSPageSize: true,
-  margin: {
-    top: 0,
-    right: 0,
-    bottom: 0,
-    left: 0,
-  }
-};
-
-class Printer extends EventEmitter {
-  constructor(headless) {
-    super();
-    this.headless = headless !== false;
-  }
-
-  async setup() {
-    const browser = await puppeteer.launch({
-      headless: this.headless
-    });
-
-    return browser;
-  }
-
-  async serve(input) {
-    let relativePath = path.resolve(dir, input);
-    let dirname = path.dirname(relativePath);
-
-    app.use("/print", express.static(dirname))
-
-    let scriptPath = path.resolve(dir, "./node_modules/pagedjs/dist/");
-    app.use("/polyfill", express.static(scriptPath))
-
-    app.set('port', process.env.PORT || 0);
-
-    return new Promise(function(resolve, reject) {
-      let server = app.listen(app.get('port'), () => {
-        resolve(server);
-      });
-    });
-  }
-
-  async render(input) {
-    let resolver;
-    let rendered = new Promise(function(resolve, reject) {
-      resolver = resolve;
-    });
-
-    if (!this.browser) {
-      this.browser = await this.setup();
-    }
-
-    const page = await this.browser.newPage();
-
-    let server = await this.serve(input);
-    let port = server.address().port;
-
-    let relativePath = path.resolve(dir, input);
-    let basename = path.basename(relativePath);
-
-    await page.goto(`http://localhost:${port}/print/${basename}`)
-      .catch((e) => {
-        console.error(e);
-      });
-
-    await page.exposeFunction('PuppeteerLogger', (msg, counter) => {
-      console.log(msg, counter);
-      this.emit(msg, counter);
-    });
-
-    await page.exposeFunction('onPagesRendered', async (msg, width, height, orientation) => {
-      console.log('onPagesRendered', msg, width, height, orientation);
-      this.emit(msg, width, height, orientation);
-      resolver({msg, width, height, orientation});
-    });
-
-    await page.addScriptTag({
-      url: `http://localhost:${port}/polyfill/paged.polyfill.js`
-    });
-
-    await rendered;
-
-    await page.waitForSelector(".pagedjs_pages");
-
-    server.close();
-
-    return page;
-  }
-
-  async pdf(input, options={}) {
-    let page = await this.render(input);
-
-    let settings = {
-      printBackground: true,
-      displayHeaderFooter: false,
-      preferCSSPageSize: options.width ? false : true,
-      width: options.width,
-      height: options.height,
-      orientation: options.orientation,
-      margin: {
-        top: 0,
-        right: 0,
-        bottom: 0,
-        left: 0,
-      }
-    }
-    let pdf = await page.pdf(PDF_SETTINGS)
-      .catch((e) => {
-        console.error(e);
-      });
-
-    await page.close();
-    return pdf;
-  }
-
-  async html(input, stayopen) {
-    let page = await this.render(input);
-
-    let content = await page.content()
-      .catch((e) => {
-        console.error(e);
-      });
-
-    await page.close();
-    return content;
-  }
-
-  async preview(input) {
-    let page = await this.render(input);
-    return page;
-  }
-
-}
+const Printer = require('./src/printer');
 
 module.exports = Printer;
diff --git a/package-lock.json b/package-lock.json
index ba4c293c50a61d56ffbd11060918be1c2e5ca541..06b59756f0db46ab4af033db83f57458c312d6bc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,29 +25,44 @@
       }
     },
     "@babel/polyfill": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.0.0.tgz",
-      "integrity": "sha512-dnrMRkyyr74CRelJwvgnnSUDh2ge2NCTyHVwpOdvRMHtJUyxLtMAfhBN3s64pY41zdw0kgiLPh6S20eb1NcX6Q==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.4.4.tgz",
+      "integrity": "sha512-WlthFLfhQQhh+A2Gn5NSFl0Huxz36x86Jn+E9OW7ibK8edKPq+KLy4apM1yDpQ8kJOVi1OVjpP4vSDLdrI04dg==",
       "requires": {
-        "core-js": "^2.5.7",
-        "regenerator-runtime": "^0.11.1"
+        "core-js": "^2.6.5",
+        "regenerator-runtime": "^0.13.2"
       }
     },
     "@babel/runtime": {
-      "version": "7.1.5",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.1.5.tgz",
-      "integrity": "sha512-xKnPpXG/pvK1B90JkwwxSGii90rQGKtzcMt2gI5G6+M0REXaq6rOHsGC2ay6/d0Uje7zzvSzjEzfR3ENhFlrfA==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.4.tgz",
+      "integrity": "sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==",
       "requires": {
-        "regenerator-runtime": "^0.12.0"
-      },
-      "dependencies": {
-        "regenerator-runtime": {
-          "version": "0.12.1",
-          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
-          "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
-        }
+        "regenerator-runtime": "^0.13.2"
+      }
+    },
+    "@pdf-lib/fontkit": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/@pdf-lib/fontkit/-/fontkit-0.0.4.tgz",
+      "integrity": "sha512-MfwaMqLKRuXXOuTisAUiie+cBH/Wo50SPBDQB5tmVqEHpJGkyh7eYi/xPgFugtPHEeWP6INUk5t9L7IAbV7jmw==",
+      "requires": {
+        "pako": "^1.0.6"
       }
     },
+    "@pdf-lib/standard-fonts": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-0.0.4.tgz",
+      "integrity": "sha512-2pg8hXnChVAF6aSFraXtwB0cx/AgE15FvuLJbdPJSq9LYp1xMp0lapH4+t1HsdD9cA05rnWYLqlEBwS4YK1jLg==",
+      "requires": {
+        "base64-arraybuffer": "^0.1.5",
+        "pako": "^1.0.6"
+      }
+    },
+    "@types/node": {
+      "version": "11.13.8",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz",
+      "integrity": "sha512-szA3x/3miL90ZJxUCzx9haNbK5/zmPieGraZEe4WI+3srN0eGLiT22NXeMHmyhNEopn+IrxqMc7wdVwvPl8meg=="
+    },
     "accepts": {
       "version": "1.3.5",
       "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
@@ -58,15 +73,15 @@
       }
     },
     "acorn": {
-      "version": "6.0.4",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz",
-      "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==",
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
+      "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
       "dev": true
     },
     "acorn-jsx": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.0.tgz",
-      "integrity": "sha512-XkB50fn0MURDyww9+UYL3c1yLbOBz0ZFvrdYlGB8l+Ije1oSC75qAqrzSPjYQbdnQUzhlUGNKuesryAv0gxZOg==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
+      "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
       "dev": true
     },
     "agent-base": {
@@ -77,10 +92,22 @@
         "es6-promisify": "^5.0.0"
       }
     },
+    "ajv": {
+      "version": "6.10.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
+      "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
+      "dev": true,
+      "requires": {
+        "fast-deep-equal": "^2.0.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      }
+    },
     "ansi-escapes": {
-      "version": "3.1.0",
-      "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
-      "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==",
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+      "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
       "dev": true
     },
     "ansi-regex": {
@@ -93,7 +120,6 @@
       "version": "3.2.1",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
       "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
       "requires": {
         "color-convert": "^1.9.0"
       }
@@ -112,6 +138,12 @@
       "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
       "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
     },
+    "astral-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+      "dev": true
+    },
     "async-limiter": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
@@ -122,6 +154,11 @@
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
     },
+    "base64-arraybuffer": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
+      "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg="
+    },
     "body-parser": {
       "version": "1.18.3",
       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
@@ -139,6 +176,11 @@
         "type-is": "~1.6.16"
       }
     },
+    "boolbase": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -158,26 +200,16 @@
       "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
       "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
     },
-    "caller-path": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
-      "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
-      "dev": true,
-      "requires": {
-        "callsites": "^0.2.0"
-      }
-    },
     "callsites": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
-      "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
       "dev": true
     },
     "chalk": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
-      "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
-      "dev": true,
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
       "requires": {
         "ansi-styles": "^3.2.1",
         "escape-string-regexp": "^1.0.5",
@@ -190,32 +222,47 @@
       "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
       "dev": true
     },
-    "circular-json": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
-      "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
-      "dev": true
+    "cheerio": {
+      "version": "1.0.0-rc.3",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
+      "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
+      "requires": {
+        "css-select": "~1.2.0",
+        "dom-serializer": "~0.1.1",
+        "entities": "~1.1.1",
+        "htmlparser2": "^3.9.1",
+        "lodash": "^4.15.0",
+        "parse5": "^3.0.1"
+      }
     },
     "cli-cursor": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
       "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
-      "dev": true,
       "requires": {
         "restore-cursor": "^2.0.0"
       }
     },
+    "cli-spinners": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.1.0.tgz",
+      "integrity": "sha512-8B00fJOEh1HPrx4fo5eW16XmE1PcL1tGpGrxy63CXGP9nHdPBN63X75hA1zhvQuhVztJWLqV58Roj2qlNM7cAA=="
+    },
     "cli-width": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
       "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
       "dev": true
     },
+    "clone": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+      "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
+    },
     "color-convert": {
       "version": "1.9.3",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
       "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "dev": true,
       "requires": {
         "color-name": "1.1.3"
       }
@@ -223,13 +270,12 @@
     "color-name": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-      "dev": true
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
     },
     "commander": {
-      "version": "2.19.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
-      "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg=="
+      "version": "2.20.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
+      "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ=="
     },
     "concat-map": {
       "version": "0.0.1",
@@ -268,9 +314,9 @@
       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
     },
     "core-js": {
-      "version": "2.5.7",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
-      "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
+      "version": "2.6.5",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
+      "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A=="
     },
     "core-util-is": {
       "version": "1.0.2",
@@ -290,6 +336,17 @@
         "which": "^1.2.9"
       }
     },
+    "css-select": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+      "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
+      "requires": {
+        "boolbase": "~1.0.0",
+        "css-what": "2.1",
+        "domutils": "1.5.1",
+        "nth-check": "~1.0.1"
+      }
+    },
     "css-tree": {
       "version": "1.0.0-alpha.29",
       "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz",
@@ -299,6 +356,11 @@
         "source-map": "^0.5.3"
       }
     },
+    "css-what": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+      "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="
+    },
     "d": {
       "version": "1.0.0",
       "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz",
@@ -321,6 +383,14 @@
       "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
       "dev": true
     },
+    "defaults": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
+      "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
+      "requires": {
+        "clone": "^1.0.2"
+      }
+    },
     "depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -332,32 +402,74 @@
       "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
     },
     "doctrine": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
-      "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
       "dev": true,
       "requires": {
         "esutils": "^2.0.2"
       }
     },
+    "dom-serializer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+      "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+      "requires": {
+        "domelementtype": "^1.3.0",
+        "entities": "^1.1.1"
+      }
+    },
+    "domelementtype": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+    },
+    "domhandler": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+      "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+      "requires": {
+        "domelementtype": "1"
+      }
+    },
+    "domutils": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+      "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+      "requires": {
+        "dom-serializer": "0",
+        "domelementtype": "1"
+      }
+    },
     "ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
     },
+    "emoji-regex": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+      "dev": true
+    },
     "encodeurl": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
       "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
     },
+    "entities": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
+    },
     "es5-ext": {
-      "version": "0.10.46",
-      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz",
-      "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==",
+      "version": "0.10.49",
+      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.49.tgz",
+      "integrity": "sha512-3NMEhi57E31qdzmYp2jwRArIUsj1HI/RxbQ4bgnSB+AIKIxsAmTiK83bYMifIcpWvEc3P1X30DhUKOqEtF/kvg==",
       "requires": {
         "es6-iterator": "~2.0.3",
         "es6-symbol": "~3.1.1",
-        "next-tick": "1"
+        "next-tick": "^1.0.0"
       }
     },
     "es6-iterator": {
@@ -371,9 +483,9 @@
       }
     },
     "es6-promise": {
-      "version": "4.2.5",
-      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz",
-      "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg=="
+      "version": "4.2.6",
+      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz",
+      "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q=="
     },
     "es6-promisify": {
       "version": "5.0.0",
@@ -400,112 +512,73 @@
     "escape-string-regexp": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-      "dev": true
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
     },
     "eslint": {
-      "version": "5.9.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.9.0.tgz",
-      "integrity": "sha512-g4KWpPdqN0nth+goDNICNXGfJF7nNnepthp46CAlJoJtC5K/cLu3NgCM3AHu1CkJ5Hzt9V0Y0PBAO6Ay/gGb+w==",
+      "version": "5.16.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz",
+      "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
-        "ajv": "^6.5.3",
+        "ajv": "^6.9.1",
         "chalk": "^2.1.0",
         "cross-spawn": "^6.0.5",
         "debug": "^4.0.1",
-        "doctrine": "^2.1.0",
-        "eslint-scope": "^4.0.0",
+        "doctrine": "^3.0.0",
+        "eslint-scope": "^4.0.3",
         "eslint-utils": "^1.3.1",
         "eslint-visitor-keys": "^1.0.0",
-        "espree": "^4.0.0",
+        "espree": "^5.0.1",
         "esquery": "^1.0.1",
         "esutils": "^2.0.2",
-        "file-entry-cache": "^2.0.0",
+        "file-entry-cache": "^5.0.1",
         "functional-red-black-tree": "^1.0.1",
         "glob": "^7.1.2",
         "globals": "^11.7.0",
         "ignore": "^4.0.6",
+        "import-fresh": "^3.0.0",
         "imurmurhash": "^0.1.4",
-        "inquirer": "^6.1.0",
-        "is-resolvable": "^1.1.0",
-        "js-yaml": "^3.12.0",
+        "inquirer": "^6.2.2",
+        "js-yaml": "^3.13.0",
         "json-stable-stringify-without-jsonify": "^1.0.1",
         "levn": "^0.3.0",
-        "lodash": "^4.17.5",
+        "lodash": "^4.17.11",
         "minimatch": "^3.0.4",
         "mkdirp": "^0.5.1",
         "natural-compare": "^1.4.0",
         "optionator": "^0.8.2",
         "path-is-inside": "^1.0.2",
-        "pluralize": "^7.0.0",
         "progress": "^2.0.0",
         "regexpp": "^2.0.1",
-        "require-uncached": "^1.0.3",
         "semver": "^5.5.1",
         "strip-ansi": "^4.0.0",
         "strip-json-comments": "^2.0.1",
-        "table": "^5.0.2",
+        "table": "^5.2.3",
         "text-table": "^0.2.0"
       },
       "dependencies": {
-        "ajv": {
-          "version": "6.5.5",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz",
-          "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==",
-          "dev": true,
-          "requires": {
-            "fast-deep-equal": "^2.0.1",
-            "fast-json-stable-stringify": "^2.0.0",
-            "json-schema-traverse": "^0.4.1",
-            "uri-js": "^4.2.2"
-          }
-        },
         "debug": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
-          "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "dev": true,
           "requires": {
             "ms": "^2.1.1"
           }
         },
-        "fast-deep-equal": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
-          "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
-          "dev": true
-        },
-        "ignore": {
-          "version": "4.0.6",
-          "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
-          "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
-          "dev": true
-        },
-        "json-schema-traverse": {
-          "version": "0.4.1",
-          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-          "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-          "dev": true
-        },
         "ms": {
           "version": "2.1.1",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
           "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
           "dev": true
-        },
-        "semver": {
-          "version": "5.6.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
-          "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
-          "dev": true
         }
       }
     },
     "eslint-scope": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
-      "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+      "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
       "dev": true,
       "requires": {
         "esrecurse": "^4.1.0",
@@ -525,16 +598,22 @@
       "dev": true
     },
     "espree": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz",
-      "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz",
+      "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==",
       "dev": true,
       "requires": {
-        "acorn": "^6.0.2",
+        "acorn": "^6.0.7",
         "acorn-jsx": "^5.0.0",
         "eslint-visitor-keys": "^1.0.0"
       }
     },
+    "esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "dev": true
+    },
     "esquery": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
@@ -649,6 +728,12 @@
         "yauzl": "2.4.1"
       }
     },
+    "fast-deep-equal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+      "dev": true
+    },
     "fast-json-stable-stringify": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
@@ -679,13 +764,12 @@
       }
     },
     "file-entry-cache": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
-      "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
+      "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
       "dev": true,
       "requires": {
-        "flat-cache": "^1.2.1",
-        "object-assign": "^4.0.1"
+        "flat-cache": "^2.0.1"
       }
     },
     "finalhandler": {
@@ -703,17 +787,22 @@
       }
     },
     "flat-cache": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
-      "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+      "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
       "dev": true,
       "requires": {
-        "circular-json": "^0.3.1",
-        "graceful-fs": "^4.1.2",
-        "rimraf": "~2.6.2",
-        "write": "^0.2.1"
+        "flatted": "^2.0.0",
+        "rimraf": "2.6.3",
+        "write": "1.0.3"
       }
     },
+    "flatted": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz",
+      "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==",
+      "dev": true
+    },
     "forwarded": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
@@ -749,22 +838,40 @@
       }
     },
     "globals": {
-      "version": "11.9.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz",
-      "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==",
-      "dev": true
-    },
-    "graceful-fs": {
-      "version": "4.1.15",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
-      "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
+      "version": "11.11.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz",
+      "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==",
       "dev": true
     },
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-      "dev": true
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+    },
+    "htmlparser2": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+      "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+      "requires": {
+        "domelementtype": "^1.3.1",
+        "domhandler": "^2.3.0",
+        "domutils": "^1.5.1",
+        "entities": "^1.1.1",
+        "inherits": "^2.0.1",
+        "readable-stream": "^3.1.1"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz",
+          "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==",
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
     },
     "http-errors": {
       "version": "1.6.3",
@@ -802,9 +909,9 @@
       }
     },
     "hyphenopoly": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/hyphenopoly/-/hyphenopoly-2.5.1.tgz",
-      "integrity": "sha512-mhJFEzFLdhJNZ5xyx3Yy58Aa5hXwVVdCQC3CL2N9keOGsLMYdafJ0B3z/JCSWbY8skgsdsuuHl3SQQMkQN8x5w=="
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/hyphenopoly/-/hyphenopoly-3.0.1.tgz",
+      "integrity": "sha512-2tAfy6wtQqDpYNGpR6bA74ea/plC2RtfTLWyJ71VbBAy52AI/JwrglS843AZOznOAAvcFm7dODbYfwTGcUiT+w=="
     },
     "iconv-lite": {
       "version": "0.4.23",
@@ -814,6 +921,22 @@
         "safer-buffer": ">= 2.1.2 < 3"
       }
     },
+    "ignore": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+      "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+      "dev": true
+    },
+    "import-fresh": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz",
+      "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==",
+      "dev": true,
+      "requires": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      }
+    },
     "imurmurhash": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -835,24 +958,41 @@
       "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
     },
     "inquirer": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz",
-      "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==",
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz",
+      "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==",
       "dev": true,
       "requires": {
-        "ansi-escapes": "^3.0.0",
-        "chalk": "^2.0.0",
+        "ansi-escapes": "^3.2.0",
+        "chalk": "^2.4.2",
         "cli-cursor": "^2.1.0",
         "cli-width": "^2.0.0",
-        "external-editor": "^3.0.0",
+        "external-editor": "^3.0.3",
         "figures": "^2.0.0",
-        "lodash": "^4.17.10",
+        "lodash": "^4.17.11",
         "mute-stream": "0.0.7",
         "run-async": "^2.2.0",
-        "rxjs": "^6.1.0",
+        "rxjs": "^6.4.0",
         "string-width": "^2.1.0",
-        "strip-ansi": "^4.0.0",
+        "strip-ansi": "^5.1.0",
         "through": "^2.3.6"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
+        }
       }
     },
     "ipaddr.js": {
@@ -872,12 +1012,6 @@
       "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
       "dev": true
     },
-    "is-resolvable": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
-      "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
-      "dev": true
-    },
     "isarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -896,23 +1030,21 @@
       "dev": true
     },
     "js-yaml": {
-      "version": "3.12.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
-      "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
+      "version": "3.13.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
       "dev": true,
       "requires": {
         "argparse": "^1.0.7",
         "esprima": "^4.0.0"
-      },
-      "dependencies": {
-        "esprima": {
-          "version": "4.0.1",
-          "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-          "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
-          "dev": true
-        }
       }
     },
+    "json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true
+    },
     "json-stable-stringify-without-jsonify": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
@@ -920,11 +1052,11 @@
       "dev": true
     },
     "katex": {
-      "version": "0.10.0",
-      "resolved": "https://registry.npmjs.org/katex/-/katex-0.10.0.tgz",
-      "integrity": "sha512-/WRvx+L1eVBrLwX7QzKU1dQuaGnE7E8hDvx3VWfZh9HbMiCfsKWJNnYZ0S8ZMDAfAyDSofdyXIrH/hujF1fYXg==",
+      "version": "0.10.1",
+      "resolved": "https://registry.npmjs.org/katex/-/katex-0.10.1.tgz",
+      "integrity": "sha512-iZXZ2L8pEP7HXBLAaeWkdLxnoRQ8Fdks8IuIVt01tYb+D8e0em5JYgfe6J48wXsuEr512IRCN5Kvwb9FjZH6kg==",
       "requires": {
-        "commander": "^2.16.0"
+        "commander": "^2.19.0"
       }
     },
     "levn": {
@@ -942,6 +1074,14 @@
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
       "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
     },
+    "log-symbols": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+      "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+      "requires": {
+        "chalk": "^2.0.1"
+      }
+    },
     "mathjax": {
       "version": "2.7.5",
       "resolved": "https://registry.npmjs.org/mathjax/-/mathjax-2.7.5.tgz",
@@ -988,8 +1128,7 @@
     "mimic-fn": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
-      "dev": true
+      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
     },
     "minimatch": {
       "version": "3.0.4",
@@ -1045,11 +1184,13 @@
       "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
       "dev": true
     },
-    "object-assign": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
-      "dev": true
+    "nth-check": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+      "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+      "requires": {
+        "boolbase": "~1.0.0"
+      }
     },
     "on-finished": {
       "version": "2.3.0",
@@ -1071,7 +1212,6 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
       "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
-      "dev": true,
       "requires": {
         "mimic-fn": "^1.0.0"
       }
@@ -1090,22 +1230,72 @@
         "wordwrap": "~1.0.0"
       }
     },
+    "ora": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz",
+      "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==",
+      "requires": {
+        "chalk": "^2.4.2",
+        "cli-cursor": "^2.1.0",
+        "cli-spinners": "^2.0.0",
+        "log-symbols": "^2.2.0",
+        "strip-ansi": "^5.2.0",
+        "wcwidth": "^1.0.1"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+        },
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
+        }
+      }
+    },
     "os-tmpdir": {
       "version": "1.0.2",
-      "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
       "dev": true
     },
     "pagedjs": {
-      "version": "0.1.26",
-      "resolved": "https://registry.npmjs.org/pagedjs/-/pagedjs-0.1.26.tgz",
-      "integrity": "sha512-FD/lXI6ACufq96koQPGEaYq6gRU0X07GBPdbnZFOCHcsLgk80MYsASLy4+rnWS9l7CdA9PQYSfSFp9dcMwIv7g==",
+      "version": "0.1.34",
+      "resolved": "https://registry.npmjs.org/pagedjs/-/pagedjs-0.1.34.tgz",
+      "integrity": "sha512-ilBSaChoy8gulel16LTz8IkFDrZdVRkSBqW+TNmmDLGzo2g32EVXekc9mHQ76LnH7KTrAU3uJns80PwQlE22nQ==",
       "requires": {
-        "@babel/polyfill": "^7.0.0",
-        "@babel/runtime": "^7.1.5",
+        "@babel/polyfill": "^7.4.4",
+        "@babel/runtime": "^7.4.4",
         "css-tree": "1.0.0-alpha.29",
         "event-emitter": "^0.3.5",
-        "lodash": "^4.17.10"
+        "lodash": "^4.17.11"
+      }
+    },
+    "pako": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz",
+      "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw=="
+    },
+    "parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "requires": {
+        "callsites": "^3.0.0"
+      }
+    },
+    "parse5": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+      "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+      "requires": {
+        "@types/node": "*"
       }
     },
     "parseurl": {
@@ -1135,16 +1325,31 @@
       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
       "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
     },
+    "pdf-lib": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-0.6.1.tgz",
+      "integrity": "sha512-26TtILsc+tsAEeK7zaSgc4AXKS+zZ6THssHFQRNGPymhy7OiPhCTXXJSwAdU2mBAnGpGfl/A2d9iW1P25kGDlg==",
+      "requires": {
+        "@pdf-lib/fontkit": "^0.0.4",
+        "@pdf-lib/standard-fonts": "^0.0.4",
+        "lodash": "^4.17.4",
+        "pako": "^1.0.6",
+        "png-ts": "^0.0.3",
+        "proxy-polyfill": "^0.3.0"
+      }
+    },
     "pend": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
       "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
     },
-    "pluralize": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
-      "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
-      "dev": true
+    "png-ts": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/png-ts/-/png-ts-0.0.3.tgz",
+      "integrity": "sha512-Qwn3yMfbrbaN86QjrDAqD1UVJc4AV4hvBCx5Dv9libLd6D20xKtgOFs/UcvD0nnjxWlgS12kEVWCDFd9ZtwB+g==",
+      "requires": {
+        "pako": "^1.0.6"
+      }
     },
     "prelude-ls": {
       "version": "1.1.2",
@@ -1158,9 +1363,9 @@
       "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
     },
     "progress": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz",
-      "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg=="
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+      "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
     },
     "proxy-addr": {
       "version": "2.0.4",
@@ -1176,33 +1381,44 @@
       "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
       "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4="
     },
+    "proxy-polyfill": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/proxy-polyfill/-/proxy-polyfill-0.3.0.tgz",
+      "integrity": "sha512-0HN+SoV3qKJ1EIIOsEybYgyTTnR26PJ0af/shBqaXLUMIg7/8PHEyQ28QfaDFwmvH77yRuLtclnERgrCq4v+xg=="
+    },
+    "punycode": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+      "dev": true
+    },
     "puppeteer": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.10.0.tgz",
-      "integrity": "sha512-3i28X/ucX8t3eL4TZA60FLMOQNKqudFSOGDHr0cT7T4dE027CrcS885aAqjdxNybhMPliM5yImNsKJ6SQrPzhw==",
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.15.0.tgz",
+      "integrity": "sha512-D2y5kwA9SsYkNUmcBzu9WZ4V1SGHiQTmgvDZSx6sRYFsgV25IebL4V6FaHjF6MbwLK9C6f3G3pmck9qmwM8H3w==",
       "requires": {
-        "debug": "^3.1.0",
+        "debug": "^4.1.0",
         "extract-zip": "^1.6.6",
         "https-proxy-agent": "^2.2.1",
         "mime": "^2.0.3",
-        "progress": "^2.0.0",
+        "progress": "^2.0.1",
         "proxy-from-env": "^1.0.0",
         "rimraf": "^2.6.1",
-        "ws": "^5.1.1"
+        "ws": "^6.1.0"
       },
       "dependencies": {
         "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "requires": {
             "ms": "^2.1.1"
           }
         },
         "mime": {
-          "version": "2.3.1",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz",
-          "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg=="
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz",
+          "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg=="
         },
         "ms": {
           "version": "2.1.1",
@@ -1247,9 +1463,9 @@
       }
     },
     "regenerator-runtime": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+      "version": "0.13.2",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz",
+      "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA=="
     },
     "regexpp": {
       "version": "2.0.1",
@@ -1262,38 +1478,27 @@
       "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
       "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs="
     },
-    "require-uncached": {
-      "version": "1.0.3",
-      "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
-      "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
-      "dev": true,
-      "requires": {
-        "caller-path": "^0.1.0",
-        "resolve-from": "^1.0.0"
-      }
-    },
     "resolve-from": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
-      "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
       "dev": true
     },
     "restore-cursor": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
       "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
-      "dev": true,
       "requires": {
         "onetime": "^2.0.0",
         "signal-exit": "^3.0.2"
       }
     },
     "rimraf": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
-      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+      "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
       "requires": {
-        "glob": "^7.0.5"
+        "glob": "^7.1.3"
       }
     },
     "run-async": {
@@ -1306,9 +1511,9 @@
       }
     },
     "rxjs": {
-      "version": "6.3.3",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
-      "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+      "version": "6.5.1",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.1.tgz",
+      "integrity": "sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg==",
       "dev": true,
       "requires": {
         "tslib": "^1.9.0"
@@ -1325,9 +1530,9 @@
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
     "semver": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
-      "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+      "version": "5.7.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+      "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
       "dev": true
     },
     "send": {
@@ -1384,15 +1589,16 @@
     "signal-exit": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
-      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
-      "dev": true
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
     },
     "slice-ansi": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
-      "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
+      "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
       "dev": true,
       "requires": {
+        "ansi-styles": "^3.2.0",
+        "astral-regex": "^1.0.0",
         "is-fullwidth-code-point": "^2.0.0"
       }
     },
@@ -1449,46 +1655,47 @@
       "version": "5.5.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
       "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
       "requires": {
         "has-flag": "^3.0.0"
       }
     },
     "table": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz",
-      "integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==",
+      "version": "5.2.3",
+      "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz",
+      "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==",
       "dev": true,
       "requires": {
-        "ajv": "^6.5.3",
-        "lodash": "^4.17.10",
-        "slice-ansi": "1.0.0",
-        "string-width": "^2.1.1"
+        "ajv": "^6.9.1",
+        "lodash": "^4.17.11",
+        "slice-ansi": "^2.1.0",
+        "string-width": "^3.0.0"
       },
       "dependencies": {
-        "ajv": {
-          "version": "6.5.5",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz",
-          "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==",
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
           "dev": true,
           "requires": {
-            "fast-deep-equal": "^2.0.1",
-            "fast-json-stable-stringify": "^2.0.0",
-            "json-schema-traverse": "^0.4.1",
-            "uri-js": "^4.2.2"
+            "emoji-regex": "^7.0.1",
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^5.1.0"
           }
         },
-        "fast-deep-equal": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
-          "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
-          "dev": true
-        },
-        "json-schema-traverse": {
-          "version": "0.4.1",
-          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-          "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-          "dev": true
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
         }
       }
     },
@@ -1500,7 +1707,7 @@
     },
     "through": {
       "version": "2.3.8",
-      "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
       "dev": true
     },
@@ -1554,14 +1761,6 @@
       "dev": true,
       "requires": {
         "punycode": "^2.1.0"
-      },
-      "dependencies": {
-        "punycode": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
-          "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
-          "dev": true
-        }
       }
     },
     "util-deprecate": {
@@ -1579,6 +1778,14 @@
       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
       "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
     },
+    "wcwidth": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+      "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
+      "requires": {
+        "defaults": "^1.0.3"
+      }
+    },
     "which": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
@@ -1600,18 +1807,18 @@
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
     },
     "write": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
-      "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
+      "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
       "dev": true,
       "requires": {
         "mkdirp": "^0.5.1"
       }
     },
     "ws": {
-      "version": "5.2.2",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
-      "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
+      "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
       "requires": {
         "async-limiter": "~1.0.0"
       }
diff --git a/package.json b/package.json
index a4dea24df603498f7b13e19261dc3eb2caff4265..5801225e8e85df1442db86b2c779e843b5269488 100644
--- a/package.json
+++ b/package.json
@@ -15,16 +15,19 @@
   },
   "main": "index.js",
   "dependencies": {
-    "commander": "^2.19.0",
+    "commander": "^2.20.0",
     "express": "^4.16.4",
-    "hyphenopoly": "^2.5.1",
-    "katex": "^0.10.0",
+    "hyphenopoly": "^3.0.1",
+    "katex": "^0.10.1",
+    "lodash": "^4.17.11",
     "mathjax": "^2.7.5",
-    "pagedjs": "^0.1.26",
-    "puppeteer": "^1.10.0",
+    "ora": "^3.4.0",
+    "pagedjs": "^0.1.34",
+    "pdf-lib": "^0.6.1",
+    "puppeteer": "^1.15.0",
     "replace-ext": "^1.0.0"
   },
   "devDependencies": {
-    "eslint": "^5.9.0"
+    "eslint": "^5.16.0"
   }
 }
diff --git a/src/postprocesser.js b/src/postprocesser.js
new file mode 100644
index 0000000000000000000000000000000000000000..635f277a3e32fd62863ad150dbc1413203d6371a
--- /dev/null
+++ b/src/postprocesser.js
@@ -0,0 +1,214 @@
+const PDFLib = require("pdf-lib");
+const EventEmitter = require('events');
+
+const PDFDocumentWriter = require('./writer');
+
+class PostProcesser extends EventEmitter {
+  constructor(pdf) {
+    super();
+
+    if (!pdf) {
+      throw "Must pass a PDF Buffer to PostProcesser"
+    }
+    this.pdf = pdf
+    this.pdfDoc = PDFLib.PDFDocumentFactory.load(pdf);
+  }
+
+  metadata(meta) {
+    if (meta.keywords && typeof meta.keywords === "string") {
+      meta.keywords = meta.keywords.split(",");
+    }
+
+    if (!meta.keywords) {
+      meta.keywords = [];
+    }
+
+    // Overwrite Dates
+    if (!(meta.creationDate instanceof Date)) {
+      meta.creationDate = new Date();
+    }
+    meta.modDate = new Date();
+    meta.metadataDate = new Date();
+
+    // Get the existing Info
+    let info = this.getInfoDict();
+    if (!meta.creator) {
+      meta.creator = info.creator + " + Paged.js";
+    }
+
+    if (!meta.producer) {
+      meta.producer = info.producer;
+    }
+
+    // Add meta
+    this.addXmpMetadata(meta);
+    this.updateInfoDict(meta);
+  }
+
+  getInfoDict(){
+    // Info Reference in Skia pdfs is always 1st
+    let ref = PDFLib.PDFIndirectReference.forNumbers(1, 0);
+    let info = this.pdfDoc.index.lookup(ref);
+    return {
+      title: info.getMaybe("Title") && info.getMaybe("Title").string,
+      subject: info.getMaybe("Subject") && info.getMaybe("Subject").string,
+      keywords: info.getMaybe("Keywords") && info.getMaybe("Keywords").string,
+      author: info.getMaybe("Author") && info.getMaybe("Author").string,
+      creationDate: info.getMaybe("CreationDate") && info.getMaybe("CreationDate").string,
+      modDate: info.getMaybe("ModDate") && info.getMaybe("ModDate").string,
+      creator: info.getMaybe("Creator") && info.getMaybe("Creator").string,
+      producer: info.getMaybe("Producer") && info.getMaybe("Producer").string
+    }
+  }
+
+  updateInfoDict(meta) {
+    // Info Reference in Skia pdfs is always 1st
+    let ref = PDFLib.PDFIndirectReference.forNumbers(1, 0);
+    let info = this.pdfDoc.index.lookup(ref);
+
+    if (meta.title) {
+      info.set("Title", PDFLib.PDFString.fromString(meta.title));
+    }
+
+    if (meta.subject) {
+      info.set("Subject", PDFLib.PDFString.fromString(meta.subject));
+    }
+
+    if (meta.keywords && meta.keywords.length) {
+      info.set("Keywords", PDFLib.PDFString.fromString(meta.keywords.join(", ")));
+    }
+
+    if (meta.author) {
+      info.set("Author", PDFLib.PDFString.fromString(meta.author));
+    }
+
+    if (meta.creationDate) {
+      info.set("CreationDate", PDFLib.PDFString.fromString(meta.creationDate.toISOString()));
+    }
+
+    if (meta.modDate) {
+      info.set("ModDate", PDFLib.PDFString.fromString(meta.modDate.toISOString()));
+    }
+
+    if (meta.creator) {
+      info.set("Creator", PDFLib.PDFString.fromString(meta.creator));
+    }
+
+    if (meta.producer) {
+      info.set("Producer", PDFLib.PDFString.fromString(meta.producer));
+    }
+  }
+
+  addXmpMetadata(meta) {
+    const charCodes = (str) => str.split('').map((c) => c.charCodeAt(0));
+    const typedArrayFor = (str) => new Uint8Array(charCodes(str));
+    const whitespacePadding = new Array(20).fill(' '.repeat(100)).join('\n');
+    const metadataXML = `
+      <?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+        <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.2-c001 63.139439, 2010/09/27-13:37:26">
+          <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+
+            <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
+              <dc:format>application/pdf</dc:format>
+              <dc:creator>
+                <rdf:Seq>
+                  <rdf:li>${meta.author}</rdf:li>
+                </rdf:Seq>
+              </dc:creator>
+              <dc:title>
+                 <rdf:Alt>
+                    <rdf:li xml:lang="x-default">${meta.title}</rdf:li>
+                 </rdf:Alt>
+              </dc:title>
+              <dc:subject>
+                <rdf:Bag>
+                  ${meta.keywords
+                    .map((keyword) => `<rdf:li>${keyword}</rdf:li>`)
+                    .join('\n')}
+                </rdf:Bag>
+              </dc:subject>
+            </rdf:Description>
+
+            <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
+              <xmp:CreatorTool>${meta.creatorTool}</xmp:CreatorTool>
+              <xmp:CreateDate>${meta.creationDate.toISOString()}</xmp:CreateDate>
+              <xmp:ModifyDate>${meta.modDate.toISOString()}</xmp:ModifyDate>
+              <xmp:MetadataDate>${meta.metadataDate.toISOString()}</xmp:MetadataDate>
+            </rdf:Description>
+
+            <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+              <pdf:Subject>${meta.subject}</pdf:Subject>
+              <pdf:Producer>${meta.producer}</pdf:Producer>
+            </rdf:Description>
+
+          </rdf:RDF>
+        </x:xmpmeta>
+        ${whitespacePadding}
+      <?xpacket end="w"?>
+    `.trim();
+
+    const metadataStreamDict = PDFLib.PDFDictionary.from(
+      {
+        Type: PDFLib.PDFName.from('Metadata'),
+        Subtype: PDFLib.PDFName.from('XML'),
+        Length: PDFLib.PDFNumber.fromNumber(metadataXML.length),
+      },
+      this.pdfDoc.index,
+    );
+
+    const metadataStream = PDFLib.PDFRawStream.from(
+      metadataStreamDict,
+      typedArrayFor(metadataXML),
+    );
+
+    const metadataStreamRef = this.pdfDoc.register(metadataStream);
+
+    this.pdfDoc.catalog.set('Metadata', metadataStreamRef);
+  };
+
+  boxes(pages) {
+    const pdfPages = this.pdfDoc.getPages();
+
+    pdfPages.forEach((pdfPage, index) => {
+      const page = pages[index];
+
+      if (!page) {
+        return; // page was not rendered
+      }
+
+      let { boxes } = page;
+
+      if (Object.is(boxes.media, boxes.crop)) {
+        return; // No bleed set
+      }
+
+      const rectangle = PDFLib.PDFArray.fromArray(
+          [
+            PDFLib.PDFNumber.fromNumber(boxes.crop.x * 2),
+            PDFLib.PDFNumber.fromNumber(boxes.crop.y * 2),
+            PDFLib.PDFNumber.fromNumber(boxes.crop.width),
+            PDFLib.PDFNumber.fromNumber(boxes.crop.height),
+          ],
+          pdfPage.index,
+        );
+
+      // pdfPage.set("ArtBox", rectangle);
+      pdfPage.set("TrimBox", rectangle);
+      pdfPage.set("CropBox", rectangle);
+    });
+
+  }
+
+  updatePageBoxes(page) {
+    console.log(page);
+  }
+
+  save() {
+    let writer = new PDFDocumentWriter();
+    const pdfBytes = writer.saveToBytesWithXRefTable(this.pdfDoc);
+    this.pdf = pdfBytes;
+    return this.pdf;
+  }
+}
+
+module.exports = PostProcesser;
diff --git a/src/printer.js b/src/printer.js
new file mode 100644
index 0000000000000000000000000000000000000000..88f6ad379b676ec0ea7a0df348931ab3477b45d6
--- /dev/null
+++ b/src/printer.js
@@ -0,0 +1,229 @@
+const Paged = require('pagedjs');
+const EventEmitter = require('events');
+const puppeteer = require('puppeteer');
+const util = require('util');
+const fs = require('fs');
+const readFile = util.promisify(fs.readFile);
+
+const path = require('path');
+
+let dir = process.cwd();
+
+let scriptPath = path.resolve(dir, "./node_modules/pagedjs/dist/");
+
+const PostProcesser = require('./postprocesser');
+
+const PDF_SETTINGS = {
+  printBackground: true,
+  displayHeaderFooter: false,
+  preferCSSPageSize: true,
+  margin: {
+    top: 0,
+    right: 0,
+    bottom: 0,
+    left: 0,
+  }
+};
+
+class Printer extends EventEmitter {
+  constructor(headless, allowLocal) {
+    super();
+    this.headless = headless !== false;
+    this.allowLocal = allowLocal;
+    this.pages = [];
+  }
+
+  async setup() {
+    const browser = await puppeteer.launch({
+      headless: this.headless,
+      args: this.allowLocal ? ['--allow-file-access-from-files'] : []
+    });
+
+    return browser;
+  }
+
+  async render(input) {
+    let resolver;
+    let rendered = new Promise(function(resolve, reject) {
+      resolver = resolve;
+    });
+
+    if (!this.browser) {
+      this.browser = await this.setup();
+    }
+
+    const page = await this.browser.newPage();
+
+    let url, html;
+    if (typeof input === "string") {
+      try {
+        url = new URL(input);
+      } catch {
+        let relativePath = path.resolve(dir, input);
+        url = "file://" + relativePath;
+      }
+    } else {
+      url = input.url;
+      html = input.html;
+    }
+
+    if (html) {
+      await page.setContent(html)
+        .catch((e) => {
+          console.error(e);
+        });
+    } else {
+      await page.goto(url)
+        .catch((e) => {
+          console.error(e);
+        });
+    }
+
+    await page.evaluate(() => {
+      window.PagedConfig = {
+        auto: false
+      }
+    });
+
+    await page.addScriptTag({
+      path: path.resolve(__dirname, "../node_modules/pagedjs/dist/paged.polyfill.js")
+    });
+
+    // await page.exposeFunction('PuppeteerLogger', (msg) => {
+    //   console.log(msg);
+    // });
+
+    await page.exposeFunction('onSize', (size) => {
+      this.emit("size", size);
+    });
+
+    await page.exposeFunction('onPage', (page) => {
+      // console.log("page", page.position + 1);
+
+      this.pages.push(page);
+
+      this.emit("page", page);
+    });
+
+    await page.exposeFunction('onRendered', (msg, width, height, orientation) => {
+      this.emit("rendered", msg, width, height, orientation);
+      resolver({msg, width, height, orientation});
+    });
+
+    await page.evaluate(() => {
+      window.PagedPolyfill.on("page", (page) => {
+        const { id, width, height, startToken, endToken, breakAfter, breakBefore, position } = page;
+
+        const mediabox = page.element.getBoundingClientRect();
+        const cropbox = page.pagebox.getBoundingClientRect();
+
+        function getPointsValue(value) {
+          return (Math.round(CSS.px(value).to("pt").value * 100) / 100);
+        }
+
+        let boxes = {
+          media: {
+            width: getPointsValue(mediabox.width),
+            height: getPointsValue(mediabox.height),
+            x: 0,
+            y: 0
+          },
+          crop: {
+            width: getPointsValue(cropbox.width),
+            height: getPointsValue(cropbox.height),
+            x: getPointsValue(cropbox.x) - getPointsValue(mediabox.x),
+            y: getPointsValue(cropbox.y) - getPointsValue(mediabox.y)
+          }
+        }
+
+        window.onPage({ id, width, height, startToken, endToken, breakAfter, breakBefore, position, boxes });
+      });
+
+      window.PagedPolyfill.on("size", (size) => {
+        window.onSize(size);
+      });
+
+      window.PagedPolyfill.on("rendered", (flow) => {
+        let msg = "Rendering " + flow.total + " pages took " + flow.performance + " milliseconds.";
+        window.onRendered(msg, flow.width, flow.height, flow.orientation);
+      });
+
+      window.PagedPolyfill.preview();
+    });
+
+    await rendered;
+
+    await page.waitForSelector(".pagedjs_pages");
+
+    return page;
+  }
+
+  async pdf(input, options={}) {
+    let page = await this.render(input);
+
+    // Get metatags
+    const meta = await page.evaluate(() => {
+      let meta = {};
+      let title = document.querySelector("title");
+      meta.title = title.textContent.trim();
+      let metaTags = document.querySelectorAll("meta");
+      [...metaTags].forEach((tag) => {
+        if (tag.name) {
+          meta[tag.name] = tag.content;
+        }
+      })
+      return meta;
+    });
+
+    let settings = {
+      printBackground: true,
+      displayHeaderFooter: false,
+      preferCSSPageSize: options.width ? false : true,
+      width: options.width,
+      height: options.height,
+      orientation: options.orientation,
+      margin: {
+        top: 0,
+        right: 0,
+        bottom: 0,
+        left: 0,
+      }
+    }
+
+    let pdf = await page.pdf(PDF_SETTINGS)
+      .catch((e) => {
+        console.error(e);
+      });
+
+    await page.close();
+
+    this.emit("postprocessing");
+
+    let post = new PostProcesser(pdf);
+    post.metadata(meta);
+    post.boxes(this.pages);
+    pdf = post.save();
+
+    return pdf;
+  }
+
+  async html(input, stayopen) {
+    let page = await this.render(input);
+
+    let content = await page.content()
+      .catch((e) => {
+        console.error(e);
+      });
+
+    await page.close();
+    return content;
+  }
+
+  async preview(input) {
+    let page = await this.render(input);
+    return page;
+  }
+
+}
+
+module.exports = Printer;
diff --git a/src/writer.js b/src/writer.js
new file mode 100644
index 0000000000000000000000000000000000000000..5907babd21e6818fbf5190fea02d5f76c9f60ecd
--- /dev/null
+++ b/src/writer.js
@@ -0,0 +1,89 @@
+const PDFLib = require("pdf-lib");
+
+const isFunction = require( 'lodash/isFunction' );
+const last = require( 'lodash/last' );
+const sortBy = require( 'lodash/sortBy' );
+const PDFXRefTableFactory  = require( 'pdf-lib/lib/core/pdf-structures/factories/PDFXRefTableFactory' ).default;
+
+const createIndirectObjectsFromIndex = ({ index }) => {
+  let catalogRef;
+
+  const streamObjects = [];
+  const nonStreamObjects = [];
+
+  index.forEach((object, ref) => {
+    if (object instanceof PDFLib.PDFCatalog) catalogRef = ref;
+    const array =
+      object instanceof PDFLib.PDFStream ? streamObjects : nonStreamObjects;
+    array.push(PDFLib.PDFIndirectObject.of(object).setReference(ref));
+  });
+
+  return { catalogRef, streamObjects, nonStreamObjects };
+};
+
+const computeOffsets = (
+  startingOffset,
+  indirectObjects,
+) =>
+  indirectObjects.map((object) => ({
+    objectNumber: object.reference.objectNumber,
+    generationNumber: object.reference.generationNumber,
+    startOffset: startingOffset,
+    endOffset: startingOffset += object.bytesSize(),
+  }));
+
+
+class PDFDocumentWriter extends PDFLib.PDFDocumentWriter {
+  constructor() {
+    super();
+  }
+
+  saveToBytesWithXRefTable(pdfDoc) {
+    const {
+      catalogRef,
+      streamObjects,
+      nonStreamObjects,
+    } = createIndirectObjectsFromIndex(pdfDoc.index);
+
+    if (!catalogRef) error('Missing PDFCatalog');
+    streamObjects.forEach((streamObj) => {
+      if (isFunction(streamObj.pdfObject.encode)) streamObj.pdfObject.encode();
+    });
+
+    const merged = [...streamObjects, ...nonStreamObjects];
+
+    const offsets = computeOffsets(pdfDoc.header.bytesSize(), merged);
+    const sortedOffsets = sortBy(offsets, 'objectNumber');
+
+    /* ===== (2) Create XRefTable and Trailer ===== */
+    const table = PDFXRefTableFactory.forOffsets(sortedOffsets);
+    const tableOffset = last(offsets).endOffset;
+    const trailer = PDFLib.PDFTrailer.from(
+      tableOffset,
+      PDFLib.PDFDictionary.from(
+        {
+          Size: PDFLib.PDFNumber.fromNumber(last(sortedOffsets).objectNumber + 1),
+          Root: catalogRef,
+          Info: PDFLib.PDFIndirectReference.forNumbers(1, 0), // TODO: this is specific to Skia
+        },
+        pdfDoc.index,
+      ),
+    );
+
+    /* ===== (3) Create buffer and copy objects into it ===== */
+    const bufferSize = tableOffset + table.bytesSize() + trailer.bytesSize();
+    const buffer = new Uint8Array(bufferSize);
+
+    let remaining = pdfDoc.header.copyBytesInto(buffer);
+    remaining = merged.reduce(
+      (remBytes, indirectObj) => indirectObj.copyBytesInto(remBytes),
+      remaining,
+    );
+    remaining = table.copyBytesInto(remaining);
+    remaining = trailer.copyBytesInto(remaining);
+
+    return buffer;
+  }
+}
+
+module.exports = PDFDocumentWriter;
diff --git a/test/samples/aurorae/index.html b/test/samples/aurorae/index.html
index e8ed586a22f22654f552691eaf5fbf7b749ac2f5..e2dd16fa0d48d2196782bc7448fa55919556f2c0 100644
--- a/test/samples/aurorae/index.html
+++ b/test/samples/aurorae/index.html
@@ -4,8 +4,10 @@
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
     <meta http-equiv="Content-Style-Type" content="text/css" />
     <title>
-      The Project Gutenberg eBook of Auroræ: Their Characters and Spectra, by J. Rand Capron.
+      Auroræ: Their Characters and Spectra.
     </title>
+    <meta name="author" content="J. Rand Capron"/>
+    <meta name="subject" content="Project Gutenberg eBook"/>
 
     <link rel="coverpage" href="images/cover.jpg" />