diff --git a/.gitignore b/.gitignore
index ebe50d5e0..6aefb3414 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*.log
+*.swp
.DS_Store
.env
.sass-cache
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 000000000..c061c9209
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,2917 @@
+{
+ "name": "crafting-guide",
+ "version": "3.2.6",
+ "lockfileVersion": 1,
+ "dependencies": {
+ "abbrev": {
+ "version": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz",
+ "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=",
+ "dev": true
+ },
+ "accepts": {
+ "version": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz",
+ "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo="
+ },
+ "acorn": {
+ "version": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz",
+ "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc="
+ },
+ "acorn-globals": {
+ "version": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz",
+ "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8="
+ },
+ "ajv": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
+ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
+ "dev": true,
+ "optional": true
+ },
+ "align-text": {
+ "version": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
+ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc="
+ },
+ "amdefine": {
+ "version": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
+ },
+ "ansi-regex": {
+ "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "aproba": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz",
+ "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==",
+ "dev": true,
+ "optional": true
+ },
+ "archiver": {
+ "version": "https://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz",
+ "integrity": "sha1-TyGU1tj5nfP1MeaIHxTxXVX6ryI=",
+ "dev": true,
+ "dependencies": {
+ "async": {
+ "version": "https://registry.npmjs.org/async/-/async-2.4.0.tgz",
+ "integrity": "sha1-SZAgDxjqW4N8LMT4wDGmmFw4VhE=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+ "dev": true
+ }
+ }
+ },
+ "archiver-utils": {
+ "version": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz",
+ "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=",
+ "dev": true,
+ "dependencies": {
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+ "dev": true
+ }
+ }
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
+ "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
+ "dev": true,
+ "optional": true
+ },
+ "argparse": {
+ "version": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
+ "dev": true
+ },
+ "array-find-index": {
+ "version": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true
+ },
+ "array-flatten": {
+ "version": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "asap": {
+ "version": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz",
+ "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0="
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+ "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
+ "dev": true,
+ "optional": true
+ },
+ "assert-plus": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+ "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
+ "dev": true,
+ "optional": true
+ },
+ "assertion-error": {
+ "version": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz",
+ "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=",
+ "dev": true
+ },
+ "async": {
+ "version": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true,
+ "optional": true
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+ "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
+ "dev": true,
+ "optional": true
+ },
+ "aws4": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
+ "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=",
+ "dev": true,
+ "optional": true
+ },
+ "backbone": {
+ "version": "https://registry.npmjs.org/backbone/-/backbone-1.3.3.tgz",
+ "integrity": "sha1-TMgOp8sWMaxHSInOQPL4vGg7KZk="
+ },
+ "balanced-match": {
+ "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+ "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=",
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
+ "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
+ "dev": true,
+ "optional": true
+ },
+ "bl": {
+ "version": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz",
+ "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=",
+ "dev": true
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+ "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+ "dev": true
+ },
+ "body-parser": {
+ "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.1.tgz",
+ "integrity": "sha1-dbO8mN3W5+DY/+dQ36ylxmmT+kc="
+ },
+ "boom": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz",
+ "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=",
+ "dev": true
+ },
+ "browser-stdout": {
+ "version": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
+ "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
+ "dev": true
+ },
+ "browserify-zlib": {
+ "version": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
+ "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=",
+ "dev": true
+ },
+ "buffer-crc32": {
+ "version": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+ "dev": true
+ },
+ "buffer-shims": {
+ "version": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
+ "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=",
+ "dev": true
+ },
+ "builtin-modules": {
+ "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
+ "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
+ },
+ "camelcase": {
+ "version": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true,
+ "optional": true
+ },
+ "center-align": {
+ "version": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60="
+ },
+ "chai": {
+ "version": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz",
+ "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "character-parser": {
+ "version": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz",
+ "integrity": "sha1-wN3kqxgnE7kZuXCVmhI+zBow/NY="
+ },
+ "clean-css": {
+ "version": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.25.tgz",
+ "integrity": "sha1-nppS1cHmvFEj4bJ4P6Zf6ViUbt4=",
+ "dependencies": {
+ "commander": {
+ "version": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
+ "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ="
+ }
+ }
+ },
+ "client-sessions": {
+ "version": "https://registry.npmjs.org/client-sessions/-/client-sessions-0.8.0.tgz",
+ "integrity": "sha1-p9jFVYrV1W8qGZ81M+tlS134k/0="
+ },
+ "cliui": {
+ "version": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+ "dependencies": {
+ "wordwrap": {
+ "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
+ }
+ }
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+ "dev": true
+ },
+ "coffee-script": {
+ "version": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.5.tgz",
+ "integrity": "sha1-gJ9FhUGRErv+RqBzrXVDrxjCc0Y=",
+ "dev": true
+ },
+ "coffeeify": {
+ "version": "https://registry.npmjs.org/coffeeify/-/coffeeify-2.1.0.tgz",
+ "integrity": "sha1-Bt6Aqoe2GUk3c0Nh3vSt4lS3Gh4=",
+ "dev": true
+ },
+ "colors": {
+ "version": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
+ "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
+ "dev": true
+ },
+ "commander": {
+ "version": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz",
+ "integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0="
+ },
+ "compress-commons": {
+ "version": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.0.tgz",
+ "integrity": "sha1-WFhwku8g03y1i68AARLJJ4/3O58=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "concat-stream": {
+ "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
+ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
+ "dev": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+ "dev": true
+ },
+ "constantinople": {
+ "version": "https://registry.npmjs.org/constantinople/-/constantinople-3.0.2.tgz",
+ "integrity": "sha1-S5RdmTeQe82Y7ldRIsOBdRZUQUE="
+ },
+ "content-disposition": {
+ "version": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
+ },
+ "content-type": {
+ "version": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz",
+ "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0="
+ },
+ "convert-source-map": {
+ "version": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz",
+ "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=",
+ "dev": true
+ },
+ "cookie": {
+ "version": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+ },
+ "cookie-parser": {
+ "version": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz",
+ "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU="
+ },
+ "cookie-signature": {
+ "version": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "cookies": {
+ "version": "https://registry.npmjs.org/cookies/-/cookies-0.7.0.tgz",
+ "integrity": "sha1-C8lh2RDDUlSYD8fJ7/XaEgEbvwA="
+ },
+ "core-util-is": {
+ "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "crafting-guide-common": {
+ "version": "5.6.0",
+ "dependencies": {
+ "abbrev": {
+ "version": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz",
+ "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8="
+ },
+ "ansi-regex": {
+ "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
+ "argparse": {
+ "version": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY="
+ },
+ "array-find-index": {
+ "version": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
+ },
+ "assertion-error": {
+ "version": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz",
+ "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw="
+ },
+ "async": {
+ "version": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="
+ },
+ "backbone": {
+ "version": "https://registry.npmjs.org/backbone/-/backbone-1.3.3.tgz",
+ "integrity": "sha1-TMgOp8sWMaxHSInOQPL4vGg7KZk="
+ },
+ "balanced-match": {
+ "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+ "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
+ },
+ "body-parser": {
+ "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz",
+ "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=",
+ "dependencies": {
+ "iconv-lite": {
+ "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
+ "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI="
+ },
+ "qs": {
+ "version": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz",
+ "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4="
+ }
+ }
+ },
+ "brace-expansion": {
+ "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz",
+ "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k="
+ },
+ "browser-stdout": {
+ "version": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
+ "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8="
+ },
+ "builtin-modules": {
+ "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8="
+ },
+ "bytes": {
+ "version": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz",
+ "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg="
+ },
+ "camelcase": {
+ "version": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
+ },
+ "camelcase-keys": {
+ "version": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc="
+ },
+ "chai": {
+ "version": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz",
+ "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc="
+ },
+ "chalk": {
+ "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg="
+ },
+ "coffee-script": {
+ "version": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.5.tgz",
+ "integrity": "sha1-gJ9FhUGRErv+RqBzrXVDrxjCc0Y="
+ },
+ "colors": {
+ "version": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM="
+ },
+ "commander": {
+ "version": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q="
+ },
+ "concat-map": {
+ "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "content-type": {
+ "version": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz",
+ "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0="
+ },
+ "currently-unhandled": {
+ "version": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o="
+ },
+ "dateformat": {
+ "version": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk="
+ },
+ "debug": {
+ "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+ "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo="
+ },
+ "decamelize": {
+ "version": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "deep-eql": {
+ "version": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
+ "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=",
+ "dependencies": {
+ "type-detect": {
+ "version": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz",
+ "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI="
+ }
+ }
+ },
+ "depd": {
+ "version": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz",
+ "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM="
+ },
+ "diff": {
+ "version": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
+ "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k="
+ },
+ "ee-first": {
+ "version": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "error-ex": {
+ "version": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
+ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw="
+ },
+ "escape-string-regexp": {
+ "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "esprima": {
+ "version": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE="
+ },
+ "eventemitter2": {
+ "version": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
+ "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas="
+ },
+ "exit": {
+ "version": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
+ },
+ "faye-websocket": {
+ "version": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ="
+ },
+ "file-sync-cmp": {
+ "version": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz",
+ "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs="
+ },
+ "find-up": {
+ "version": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8="
+ },
+ "findup-sync": {
+ "version": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz",
+ "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=",
+ "dependencies": {
+ "glob": {
+ "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E="
+ }
+ }
+ },
+ "formatio": {
+ "version": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz",
+ "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs="
+ },
+ "fs.realpath": {
+ "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "gaze": {
+ "version": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz",
+ "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU="
+ },
+ "get-stdin": {
+ "version": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
+ },
+ "getobject": {
+ "version": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz",
+ "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw="
+ },
+ "glob": {
+ "version": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+ "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo="
+ },
+ "globule": {
+ "version": "https://registry.npmjs.org/globule/-/globule-1.1.0.tgz",
+ "integrity": "sha1-xJNS5NwYPYWJPuglOF65lLtt9F8=",
+ "dependencies": {
+ "glob": {
+ "version": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
+ "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg="
+ },
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.16.6.tgz",
+ "integrity": "sha1-0iyaxmAojzhD4Wun0rXQbMon13c="
+ }
+ }
+ },
+ "graceful-fs": {
+ "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
+ },
+ "graceful-readlink": {
+ "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU="
+ },
+ "growl": {
+ "version": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
+ "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8="
+ },
+ "grunt": {
+ "version": "https://registry.npmjs.org/grunt/-/grunt-1.0.1.tgz",
+ "integrity": "sha1-6HeHZOlEsY8yuw8QuQeEdcnftWs=",
+ "dependencies": {
+ "coffee-script": {
+ "version": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz",
+ "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA="
+ },
+ "grunt-cli": {
+ "version": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz",
+ "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg="
+ }
+ }
+ },
+ "grunt-contrib-clean": {
+ "version": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.1.0.tgz",
+ "integrity": "sha1-Vkq/LQN4qYOhW54/MO51tzjEBjg=",
+ "dependencies": {
+ "rimraf": {
+ "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
+ "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0="
+ }
+ }
+ },
+ "grunt-contrib-coffee": {
+ "version": "https://registry.npmjs.org/grunt-contrib-coffee/-/grunt-contrib-coffee-1.0.0.tgz",
+ "integrity": "sha1-2u6wSVTxTihovMm6bq+RBf3C2kw=",
+ "dependencies": {
+ "ansi-regex": {
+ "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz",
+ "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0="
+ },
+ "chalk": {
+ "version": "https://registry.npmjs.org/chalk/-/chalk-1.0.0.tgz",
+ "integrity": "sha1-s89O0P9Tl8mcdbj2edsvUoMfltw="
+ },
+ "coffee-script": {
+ "version": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz",
+ "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA="
+ },
+ "has-ansi": {
+ "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-1.0.3.tgz",
+ "integrity": "sha1-wLWxYV2eOCsP9nFp2We0JeSMpTg="
+ },
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
+ "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ="
+ },
+ "strip-ansi": {
+ "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz",
+ "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4="
+ },
+ "supports-color": {
+ "version": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz",
+ "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0="
+ }
+ }
+ },
+ "grunt-contrib-copy": {
+ "version": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz",
+ "integrity": "sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM="
+ },
+ "grunt-contrib-watch": {
+ "version": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz",
+ "integrity": "sha1-hKGnodar0m7VaEE0lscxM+mQAY8="
+ },
+ "grunt-known-options": {
+ "version": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz",
+ "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk="
+ },
+ "grunt-legacy-log": {
+ "version": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-1.0.0.tgz",
+ "integrity": "sha1-+4bxgJhHvAfcR4Q/ns1srLYt8tU=",
+ "dependencies": {
+ "underscore.string": {
+ "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz",
+ "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to="
+ }
+ }
+ },
+ "grunt-legacy-log-utils": {
+ "version": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz",
+ "integrity": "sha1-p7ji0Ps1taUPSvmG/BEnSevJbz0=",
+ "dependencies": {
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
+ "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ="
+ }
+ }
+ },
+ "grunt-legacy-util": {
+ "version": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz",
+ "integrity": "sha1-OGqnjcbtUJhsKxiVcmWxtIq7m4Y=",
+ "dependencies": {
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
+ "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ="
+ },
+ "underscore.string": {
+ "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz",
+ "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to="
+ }
+ }
+ },
+ "grunt-mocha-test": {
+ "version": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.13.2.tgz",
+ "integrity": "sha1-Dzq8xqtUNkex7/xatE69NwLwq4w="
+ },
+ "has-ansi": {
+ "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE="
+ },
+ "has-flag": {
+ "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo="
+ },
+ "hooker": {
+ "version": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz",
+ "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk="
+ },
+ "hosted-git-info": {
+ "version": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz",
+ "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc="
+ },
+ "http-errors": {
+ "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz",
+ "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI="
+ },
+ "iconv-lite": {
+ "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.16.tgz",
+ "integrity": "sha1-Zd477rOeKWDWfwSfFjT/y83pAUs="
+ },
+ "indent-string": {
+ "version": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA="
+ },
+ "inflight": {
+ "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk="
+ },
+ "inherits": {
+ "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "is-arrayish": {
+ "version": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+ },
+ "is-builtin-module": {
+ "version": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74="
+ },
+ "is-finite": {
+ "version": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko="
+ },
+ "is-utf8": {
+ "version": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
+ },
+ "isarray": {
+ "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+ },
+ "isexe": {
+ "version": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "js-yaml": {
+ "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz",
+ "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74="
+ },
+ "json3": {
+ "version": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
+ "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE="
+ },
+ "livereload-js": {
+ "version": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz",
+ "integrity": "sha1-bIclfmSKtHW8JOoldFftzB+NC8I="
+ },
+ "load-json-file": {
+ "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA="
+ },
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+ },
+ "lodash._baseassign": {
+ "version": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
+ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4="
+ },
+ "lodash._basecopy": {
+ "version": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
+ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY="
+ },
+ "lodash._basecreate": {
+ "version": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz",
+ "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE="
+ },
+ "lodash._getnative": {
+ "version": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+ "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
+ },
+ "lodash._isiterateecall": {
+ "version": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
+ "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw="
+ },
+ "lodash.create": {
+ "version": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz",
+ "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c="
+ },
+ "lodash.isarguments": {
+ "version": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo="
+ },
+ "lodash.isarray": {
+ "version": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U="
+ },
+ "lodash.keys": {
+ "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo="
+ },
+ "lolex": {
+ "version": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz",
+ "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY="
+ },
+ "loud-rejection": {
+ "version": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8="
+ },
+ "map-obj": {
+ "version": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
+ },
+ "media-typer": {
+ "version": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "meow": {
+ "version": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs="
+ },
+ "mime-db": {
+ "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz",
+ "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE="
+ },
+ "mime-types": {
+ "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz",
+ "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0="
+ },
+ "minimatch": {
+ "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz",
+ "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q="
+ },
+ "minimist": {
+ "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ },
+ "mkdirp": {
+ "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dependencies": {
+ "minimist": {
+ "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ }
+ }
+ },
+ "mocha": {
+ "version": "https://registry.npmjs.org/mocha/-/mocha-3.3.0.tgz",
+ "integrity": "sha1-0pt0KNP1LILi5l3x7LcGThqrv7U=",
+ "dependencies": {
+ "debug": {
+ "version": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz",
+ "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs="
+ },
+ "glob": {
+ "version": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
+ "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg="
+ },
+ "ms": {
+ "version": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+ "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U="
+ },
+ "supports-color": {
+ "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
+ "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU="
+ }
+ }
+ },
+ "ms": {
+ "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+ "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg="
+ },
+ "native-promise-only": {
+ "version": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz",
+ "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE="
+ },
+ "nopt": {
+ "version": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k="
+ },
+ "normalize-package-data": {
+ "version": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz",
+ "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs="
+ },
+ "number-is-nan": {
+ "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+ },
+ "object-assign": {
+ "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "on-finished": {
+ "version": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc="
+ },
+ "once": {
+ "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E="
+ },
+ "parse-json": {
+ "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck="
+ },
+ "parseurl": {
+ "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz",
+ "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY="
+ },
+ "path-exists": {
+ "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s="
+ },
+ "path-is-absolute": {
+ "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-to-regexp": {
+ "version": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
+ "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30="
+ },
+ "path-type": {
+ "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE="
+ },
+ "pify": {
+ "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ },
+ "pinkie": {
+ "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+ },
+ "pinkie-promise": {
+ "version": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o="
+ },
+ "qs": {
+ "version": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz",
+ "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk="
+ },
+ "raw-body": {
+ "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz",
+ "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=",
+ "dependencies": {
+ "bytes": {
+ "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
+ "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
+ },
+ "iconv-lite": {
+ "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
+ "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI="
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg="
+ },
+ "read-pkg-up": {
+ "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI="
+ },
+ "redent": {
+ "version": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94="
+ },
+ "repeating": {
+ "version": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo="
+ },
+ "resolve": {
+ "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs="
+ },
+ "rimraf": {
+ "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
+ "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI="
+ },
+ "samsam": {
+ "version": "https://registry.npmjs.org/samsam/-/samsam-1.2.1.tgz",
+ "integrity": "sha1-7dOQk6MYQ3DLhZJDsr3yVefY6mc="
+ },
+ "semver": {
+ "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+ "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
+ },
+ "signal-exit": {
+ "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ },
+ "sinon": {
+ "version": "https://registry.npmjs.org/sinon/-/sinon-2.1.0.tgz",
+ "integrity": "sha1-4Fep0r8bMvXW3WJijKnuOWGwyvs=",
+ "dependencies": {
+ "type-detect": {
+ "version": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz",
+ "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo="
+ }
+ }
+ },
+ "sinon-chai": {
+ "version": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.9.0.tgz",
+ "integrity": "sha1-NNggBCvJZhoUUnEw1AHrRixJu4Q="
+ },
+ "spdx-correct": {
+ "version": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
+ "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A="
+ },
+ "spdx-expression-parse": {
+ "version": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
+ "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw="
+ },
+ "spdx-license-ids": {
+ "version": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
+ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc="
+ },
+ "sprintf-js": {
+ "version": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ },
+ "statuses": {
+ "version": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
+ },
+ "strip-ansi": {
+ "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="
+ },
+ "strip-bom": {
+ "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4="
+ },
+ "strip-indent": {
+ "version": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI="
+ },
+ "supports-color": {
+ "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ },
+ "text-encoding": {
+ "version": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz",
+ "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk="
+ },
+ "tiny-lr": {
+ "version": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz",
+ "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0="
+ },
+ "trim-newlines": {
+ "version": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM="
+ },
+ "type-detect": {
+ "version": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz",
+ "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI="
+ },
+ "type-is": {
+ "version": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
+ "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA="
+ },
+ "underscore": {
+ "version": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
+ "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
+ },
+ "underscore.inflections": {
+ "version": "https://registry.npmjs.org/underscore.inflections/-/underscore.inflections-0.2.1.tgz",
+ "integrity": "sha1-EBvTWeAq8pOqWhBidI6WPiCHZ/E="
+ },
+ "underscore.string": {
+ "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz",
+ "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s="
+ },
+ "unpipe": {
+ "version": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "uri-path": {
+ "version": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz",
+ "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI="
+ },
+ "util-deprecate": {
+ "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "uuid": {
+ "version": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",
+ "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE="
+ },
+ "validate-npm-package-license": {
+ "version": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
+ "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w="
+ },
+ "websocket-driver": {
+ "version": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz",
+ "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY="
+ },
+ "websocket-extensions": {
+ "version": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz",
+ "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec="
+ },
+ "when": {
+ "version": "https://registry.npmjs.org/when/-/when-3.7.8.tgz",
+ "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I="
+ },
+ "which": {
+ "version": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
+ "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU="
+ },
+ "wrappy": {
+ "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ }
+ }
+ },
+ "crc": {
+ "version": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz",
+ "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms="
+ },
+ "crc32-stream": {
+ "version": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz",
+ "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-0.2.9.tgz",
+ "integrity": "sha1-vWf5bAfvtjA7f+lMHpefiEeOCjk=",
+ "dev": true
+ },
+ "cryptiles": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+ "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
+ "dev": true,
+ "optional": true
+ },
+ "css": {
+ "version": "https://registry.npmjs.org/css/-/css-1.0.8.tgz",
+ "integrity": "sha1-k4aBHKgrzMnuf7WnMrHioxfIo+c="
+ },
+ "css-parse": {
+ "version": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz",
+ "integrity": "sha1-OLBQP7+dqfVOnB29pg4UXHcRe90="
+ },
+ "css-stringify": {
+ "version": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz",
+ "integrity": "sha1-sNBClG2ylTu50pKQCmy19tASIDE="
+ },
+ "currently-unhandled": {
+ "version": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true
+ },
+ "dargs": {
+ "version": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz",
+ "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=",
+ "dev": true
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "dateformat": {
+ "version": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+ "dev": true
+ },
+ "debug": {
+ "version": "https://registry.npmjs.org/debug/-/debug-2.6.1.tgz",
+ "integrity": "sha1-eYVQkLosTjEVzH2HaUkdWPBJE1E="
+ },
+ "decamelize": {
+ "version": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "deep-eql": {
+ "version": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
+ "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=",
+ "dev": true,
+ "dependencies": {
+ "type-detect": {
+ "version": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz",
+ "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=",
+ "dev": true
+ }
+ }
+ },
+ "deep-extend": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
+ "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=",
+ "dev": true,
+ "optional": true
+ },
+ "define-properties": {
+ "version": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
+ "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
+ "dev": true
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+ "dev": true,
+ "optional": true
+ },
+ "depd": {
+ "version": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz",
+ "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM="
+ },
+ "destroy": {
+ "version": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "diff": {
+ "version": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
+ "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=",
+ "dev": true
+ },
+ "dotenv": {
+ "version": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz",
+ "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0="
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+ "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+ "dev": true,
+ "optional": true
+ },
+ "ee-first": {
+ "version": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "encodeurl": {
+ "version": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz",
+ "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA="
+ },
+ "end-of-stream": {
+ "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz",
+ "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=",
+ "dev": true
+ },
+ "error-ex": {
+ "version": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
+ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
+ "dev": true
+ },
+ "escape-html": {
+ "version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "escape-string-regexp": {
+ "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "esprima": {
+ "version": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+ "dev": true
+ },
+ "etag": {
+ "version": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz",
+ "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE="
+ },
+ "eventemitter2": {
+ "version": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
+ "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=",
+ "dev": true
+ },
+ "exit": {
+ "version": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true
+ },
+ "express": {
+ "version": "https://registry.npmjs.org/express/-/express-4.15.2.tgz",
+ "integrity": "sha1-rxB/wUhQRFfy3Kmm8lcdcSm5ezU="
+ },
+ "express-session": {
+ "version": "https://registry.npmjs.org/express-session/-/express-session-1.15.2.tgz",
+ "integrity": "sha1-2YUWRDpMy4aI4XJa5YTALapAk9Q=",
+ "dependencies": {
+ "debug": {
+ "version": "https://registry.npmjs.org/debug/-/debug-2.6.3.tgz",
+ "integrity": "sha1-D364wwll7AjHKsz6ATDIt5mEFB0="
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
+ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
+ "dev": true,
+ "optional": true
+ },
+ "extsprintf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz",
+ "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=",
+ "dev": true
+ },
+ "faye-websocket": {
+ "version": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+ "dev": true
+ },
+ "figures": {
+ "version": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+ "dev": true
+ },
+ "file-sync-cmp": {
+ "version": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz",
+ "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=",
+ "dev": true
+ },
+ "finalhandler": {
+ "version": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.2.tgz",
+ "integrity": "sha1-0ONvnbxVfy3hRCPfYmGInp1gyTo=",
+ "dependencies": {
+ "debug": {
+ "version": "https://registry.npmjs.org/debug/-/debug-2.6.4.tgz",
+ "integrity": "sha1-dYaps8OXQcAoKuM0RcTorHRzT+A="
+ },
+ "ms": {
+ "version": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz",
+ "integrity": "sha1-cIFVpeROM/X9D8U+gdDUCpG+H/8="
+ }
+ }
+ },
+ "find-up": {
+ "version": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true
+ },
+ "findup-sync": {
+ "version": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz",
+ "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=",
+ "dev": true,
+ "dependencies": {
+ "glob": {
+ "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "dev": true
+ }
+ }
+ },
+ "foreach": {
+ "version": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
+ "dev": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true,
+ "optional": true
+ },
+ "form-data": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
+ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
+ "dev": true,
+ "optional": true
+ },
+ "formatio": {
+ "version": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz",
+ "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=",
+ "dev": true
+ },
+ "forwarded": {
+ "version": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz",
+ "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M="
+ },
+ "fresh": {
+ "version": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz",
+ "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44="
+ },
+ "fs.realpath": {
+ "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
+ "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
+ "dev": true
+ },
+ "fstream-ignore": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz",
+ "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz",
+ "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=",
+ "dev": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "dev": true,
+ "optional": true
+ },
+ "gaze": {
+ "version": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz",
+ "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=",
+ "dev": true
+ },
+ "get-stdin": {
+ "version": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "getobject": {
+ "version": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz",
+ "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=",
+ "dev": true
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "glob": {
+ "version": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+ "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
+ "dev": true
+ },
+ "globule": {
+ "version": "https://registry.npmjs.org/globule/-/globule-1.1.0.tgz",
+ "integrity": "sha1-xJNS5NwYPYWJPuglOF65lLtt9F8=",
+ "dev": true,
+ "dependencies": {
+ "glob": {
+ "version": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
+ "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.16.6.tgz",
+ "integrity": "sha1-0iyaxmAojzhD4Wun0rXQbMon13c=",
+ "dev": true
+ }
+ }
+ },
+ "graceful-fs": {
+ "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "dev": true
+ },
+ "graceful-readlink": {
+ "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU="
+ },
+ "growl": {
+ "version": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
+ "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
+ "dev": true
+ },
+ "grunt": {
+ "version": "https://registry.npmjs.org/grunt/-/grunt-1.0.1.tgz",
+ "integrity": "sha1-6HeHZOlEsY8yuw8QuQeEdcnftWs=",
+ "dev": true,
+ "dependencies": {
+ "coffee-script": {
+ "version": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz",
+ "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA=",
+ "dev": true
+ },
+ "grunt-cli": {
+ "version": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz",
+ "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-contrib-clean": {
+ "version": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.1.0.tgz",
+ "integrity": "sha1-Vkq/LQN4qYOhW54/MO51tzjEBjg=",
+ "dev": true,
+ "dependencies": {
+ "rimraf": {
+ "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
+ "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-contrib-coffee": {
+ "version": "https://registry.npmjs.org/grunt-contrib-coffee/-/grunt-contrib-coffee-1.0.0.tgz",
+ "integrity": "sha1-2u6wSVTxTihovMm6bq+RBf3C2kw=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": {
+ "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz",
+ "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "https://registry.npmjs.org/chalk/-/chalk-1.0.0.tgz",
+ "integrity": "sha1-s89O0P9Tl8mcdbj2edsvUoMfltw=",
+ "dev": true
+ },
+ "coffee-script": {
+ "version": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz",
+ "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA=",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-1.0.3.tgz",
+ "integrity": "sha1-wLWxYV2eOCsP9nFp2We0JeSMpTg=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
+ "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz",
+ "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz",
+ "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-contrib-compress": {
+ "version": "https://registry.npmjs.org/grunt-contrib-compress/-/grunt-contrib-compress-1.4.1.tgz",
+ "integrity": "sha1-NiEum7tB6bQf9vvi/HcoHGmrAqA=",
+ "dev": true,
+ "dependencies": {
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-contrib-copy": {
+ "version": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz",
+ "integrity": "sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=",
+ "dev": true
+ },
+ "grunt-contrib-jade": {
+ "version": "https://registry.npmjs.org/grunt-contrib-jade/-/grunt-contrib-jade-1.0.0.tgz",
+ "integrity": "sha1-tVe8uc0uczrU4gkOEpvrIBsLhFw=",
+ "dev": true
+ },
+ "grunt-contrib-sass": {
+ "version": "https://registry.npmjs.org/grunt-contrib-sass/-/grunt-contrib-sass-1.0.0.tgz",
+ "integrity": "sha1-gGg4JRy8DhqU1k1RXN00z2dNcBs=",
+ "dev": true,
+ "dependencies": {
+ "async": {
+ "version": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
+ "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-contrib-uglify": {
+ "version": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-2.3.0.tgz",
+ "integrity": "sha1-s9AmDr3WzvoS/y+Onh4ln33kIW8=",
+ "dev": true
+ },
+ "grunt-contrib-watch": {
+ "version": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz",
+ "integrity": "sha1-hKGnodar0m7VaEE0lscxM+mQAY8=",
+ "dev": true
+ },
+ "grunt-known-options": {
+ "version": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz",
+ "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=",
+ "dev": true
+ },
+ "grunt-legacy-log": {
+ "version": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-1.0.0.tgz",
+ "integrity": "sha1-+4bxgJhHvAfcR4Q/ns1srLYt8tU=",
+ "dev": true,
+ "dependencies": {
+ "underscore.string": {
+ "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz",
+ "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-legacy-log-utils": {
+ "version": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz",
+ "integrity": "sha1-p7ji0Ps1taUPSvmG/BEnSevJbz0=",
+ "dev": true,
+ "dependencies": {
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
+ "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-legacy-util": {
+ "version": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz",
+ "integrity": "sha1-OGqnjcbtUJhsKxiVcmWxtIq7m4Y=",
+ "dev": true,
+ "dependencies": {
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
+ "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=",
+ "dev": true
+ },
+ "underscore.string": {
+ "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz",
+ "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-mocha-test": {
+ "version": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.13.2.tgz",
+ "integrity": "sha1-Dzq8xqtUNkex7/xatE69NwLwq4w=",
+ "dev": true
+ },
+ "grunt-sass-globbing": {
+ "version": "https://registry.npmjs.org/grunt-sass-globbing/-/grunt-sass-globbing-1.5.1.tgz",
+ "integrity": "sha1-nmCVXNjLP0lt3QfPcc+UQFsjgtE=",
+ "dev": true
+ },
+ "gzip-size": {
+ "version": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz",
+ "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=",
+ "dev": true
+ },
+ "har-schema": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
+ "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=",
+ "dev": true,
+ "optional": true
+ },
+ "har-validator": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
+ "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
+ "dev": true,
+ "optional": true
+ },
+ "has-ansi": {
+ "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+ "dev": true,
+ "optional": true
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+ "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
+ "dev": true,
+ "optional": true
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+ "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
+ "dev": true
+ },
+ "hooker": {
+ "version": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz",
+ "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz",
+ "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz",
+ "integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc="
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+ "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
+ "dev": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz",
+ "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es="
+ },
+ "iltorb": {
+ "version": "https://registry.npmjs.org/iltorb/-/iltorb-1.2.1.tgz",
+ "integrity": "sha1-hqfJJF8GxRqL94L0YZTY+yYMLnE=",
+ "dev": true,
+ "optional": true
+ },
+ "indent-string": {
+ "version": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true
+ },
+ "inherits": {
+ "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ini": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
+ "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=",
+ "dev": true,
+ "optional": true
+ },
+ "ipaddr.js": {
+ "version": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz",
+ "integrity": "sha1-HgOlL9rYOou7KyXL9JmLTP/NPew="
+ },
+ "is-arrayish": {
+ "version": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-buffer": {
+ "version": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz",
+ "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw="
+ },
+ "is-builtin-module": {
+ "version": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true
+ },
+ "is-promise": {
+ "version": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true,
+ "optional": true
+ },
+ "is-utf8": {
+ "version": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true,
+ "optional": true
+ },
+ "jade": {
+ "version": "https://registry.npmjs.org/jade/-/jade-1.11.0.tgz",
+ "integrity": "sha1-nIDlOMEtP7lcjZu5VZ+gzAQEBf0="
+ },
+ "jquery": {
+ "version": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz",
+ "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c="
+ },
+ "js-yaml": {
+ "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz",
+ "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=",
+ "dev": true
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true,
+ "optional": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+ "dev": true,
+ "optional": true
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+ "dev": true,
+ "optional": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true,
+ "optional": true
+ },
+ "json3": {
+ "version": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
+ "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
+ "dev": true
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+ "dev": true,
+ "optional": true
+ },
+ "jsprim": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz",
+ "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "jstransformer": {
+ "version": "https://registry.npmjs.org/jstransformer/-/jstransformer-0.0.2.tgz",
+ "integrity": "sha1-eq4pqQPRls+glz2IXT5HlH7Ndqs="
+ },
+ "keygrip": {
+ "version": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.1.tgz",
+ "integrity": "sha1-sC+kgW7vIajEs1yp5Skh/8iaMOk="
+ },
+ "kind-of": {
+ "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.0.tgz",
+ "integrity": "sha1-tYq+TVwEStM3JqjBUltIz4kb/wc="
+ },
+ "lazy-cache": {
+ "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
+ },
+ "lazystream": {
+ "version": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
+ "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
+ "dev": true
+ },
+ "livereload-js": {
+ "version": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz",
+ "integrity": "sha1-bIclfmSKtHW8JOoldFftzB+NC8I=",
+ "dev": true
+ },
+ "load-json-file": {
+ "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
+ "dev": true
+ },
+ "lodash._baseassign": {
+ "version": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
+ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=",
+ "dev": true
+ },
+ "lodash._basecopy": {
+ "version": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
+ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
+ "dev": true
+ },
+ "lodash._basecreate": {
+ "version": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz",
+ "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=",
+ "dev": true
+ },
+ "lodash._getnative": {
+ "version": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+ "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
+ "dev": true
+ },
+ "lodash._isiterateecall": {
+ "version": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
+ "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
+ "dev": true
+ },
+ "lodash.create": {
+ "version": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz",
+ "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=",
+ "dev": true
+ },
+ "lodash.isarguments": {
+ "version": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
+ "dev": true
+ },
+ "lodash.isarray": {
+ "version": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
+ "dev": true
+ },
+ "lodash.keys": {
+ "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
+ "dev": true
+ },
+ "lolex": {
+ "version": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz",
+ "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=",
+ "dev": true
+ },
+ "longest": {
+ "version": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
+ "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
+ },
+ "loud-rejection": {
+ "version": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
+ "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
+ "dev": true
+ },
+ "map-obj": {
+ "version": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ },
+ "marked": {
+ "version": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz",
+ "integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc="
+ },
+ "maxmin": {
+ "version": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz",
+ "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=",
+ "dev": true,
+ "dependencies": {
+ "pretty-bytes": {
+ "version": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
+ "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=",
+ "dev": true
+ }
+ }
+ },
+ "media-typer": {
+ "version": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "meow": {
+ "version": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true
+ },
+ "merge-descriptors": {
+ "version": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "methods": {
+ "version": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz",
+ "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM="
+ },
+ "mime-db": {
+ "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz",
+ "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE="
+ },
+ "mime-types": {
+ "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz",
+ "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0="
+ },
+ "minimatch": {
+ "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz",
+ "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=",
+ "dev": true
+ },
+ "minimist": {
+ "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dependencies": {
+ "minimist": {
+ "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ }
+ }
+ },
+ "mocha": {
+ "version": "https://registry.npmjs.org/mocha/-/mocha-3.3.0.tgz",
+ "integrity": "sha1-0pt0KNP1LILi5l3x7LcGThqrv7U=",
+ "dev": true,
+ "dependencies": {
+ "commander": {
+ "version": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
+ "dev": true
+ },
+ "debug": {
+ "version": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz",
+ "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=",
+ "dev": true
+ },
+ "glob": {
+ "version": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
+ "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
+ "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=",
+ "dev": true
+ }
+ }
+ },
+ "ms": {
+ "version": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+ "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U="
+ },
+ "nan": {
+ "version": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz",
+ "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=",
+ "dev": true,
+ "optional": true
+ },
+ "native-promise-only": {
+ "version": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz",
+ "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=",
+ "dev": true
+ },
+ "negotiator": {
+ "version": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+ },
+ "node-pre-gyp": {
+ "version": "0.6.36",
+ "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz",
+ "integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "nopt": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
+ "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
+ "dev": true,
+ "optional": true
+ },
+ "rimraf": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
+ "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "nopt": {
+ "version": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+ "dev": true
+ },
+ "normalize-package-data": {
+ "version": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz",
+ "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs=",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "dev": true,
+ "optional": true
+ },
+ "number-is-nan": {
+ "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+ "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
+ "dev": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
+ "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=",
+ "dev": true
+ },
+ "object.assign": {
+ "version": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz",
+ "integrity": "sha1-scnMBE7xuf5jYG/BQau7MuFHMMw=",
+ "dev": true
+ },
+ "on-finished": {
+ "version": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc="
+ },
+ "on-headers": {
+ "version": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
+ "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c="
+ },
+ "once": {
+ "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true
+ },
+ "optimist": {
+ "version": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz",
+ "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk="
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
+ "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
+ "dev": true,
+ "optional": true
+ },
+ "pako": {
+ "version": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
+ "dev": true
+ },
+ "parse-json": {
+ "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true
+ },
+ "parseurl": {
+ "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz",
+ "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY="
+ },
+ "path-exists": {
+ "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "path-type": {
+ "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true
+ },
+ "performance-now": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
+ "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=",
+ "dev": true,
+ "optional": true
+ },
+ "pify": {
+ "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true
+ },
+ "pretty-bytes": {
+ "version": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz",
+ "integrity": "sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+ "dev": true
+ },
+ "promise": {
+ "version": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz",
+ "integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY="
+ },
+ "proxy-addr": {
+ "version": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.4.tgz",
+ "integrity": "sha1-J+VF9pYKRKYn2bREZ+NcG2tM4vM="
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true,
+ "optional": true
+ },
+ "qs": {
+ "version": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
+ "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM="
+ },
+ "random-bytes": {
+ "version": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
+ "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
+ },
+ "range-parser": {
+ "version": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
+ },
+ "raw-body": {
+ "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz",
+ "integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y="
+ },
+ "rc": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz",
+ "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=",
+ "dev": true,
+ "optional": true
+ },
+ "read-pkg": {
+ "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true
+ },
+ "read-pkg-up": {
+ "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz",
+ "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=",
+ "dev": true
+ },
+ "redent": {
+ "version": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true
+ },
+ "remove-trailing-separator": {
+ "version": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz",
+ "integrity": "sha1-YV67lq9VlVLUv0BXyENtSGq2PMQ=",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
+ },
+ "repeating": {
+ "version": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true
+ },
+ "request": {
+ "version": "2.81.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
+ "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
+ "dev": true,
+ "optional": true
+ },
+ "resolve": {
+ "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+ "dev": true
+ },
+ "right-align": {
+ "version": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
+ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8="
+ },
+ "rimraf": {
+ "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
+ "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
+ "dev": true
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+ "dev": true
+ },
+ "samsam": {
+ "version": "https://registry.npmjs.org/samsam/-/samsam-1.2.1.tgz",
+ "integrity": "sha1-7dOQk6MYQ3DLhZJDsr3yVefY6mc=",
+ "dev": true
+ },
+ "sass": {
+ "version": "https://registry.npmjs.org/sass/-/sass-0.5.0.tgz",
+ "integrity": "sha1-ne4Rg6D0ADYfLF00U78uVHBeA/k=",
+ "dev": true
+ },
+ "semver": {
+ "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+ "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
+ "dev": true
+ },
+ "send": {
+ "version": "https://registry.npmjs.org/send/-/send-0.15.1.tgz",
+ "integrity": "sha1-igI1TCbm9cynAAZfXwzeupDse18="
+ },
+ "serve-static": {
+ "version": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.1.tgz",
+ "integrity": "sha1-dEOpZePO1kes61Y5+ga/TRu+ADk="
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true,
+ "optional": true
+ },
+ "setprototypeof": {
+ "version": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+ "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ="
+ },
+ "signal-exit": {
+ "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+ "dev": true
+ },
+ "sinon": {
+ "version": "https://registry.npmjs.org/sinon/-/sinon-2.2.0.tgz",
+ "integrity": "sha1-OxtC/13vy/UaUqYqym1hFxuf0mI=",
+ "dev": true,
+ "dependencies": {
+ "isarray": {
+ "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
+ "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
+ "dev": true
+ },
+ "type-detect": {
+ "version": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz",
+ "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=",
+ "dev": true
+ }
+ }
+ },
+ "sinon-chai": {
+ "version": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.10.0.tgz",
+ "integrity": "sha1-arMAi7jK6ZKedE12ZXS0zzXzS1s=",
+ "dev": true
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
+ "dev": true,
+ "optional": true
+ },
+ "source-map": {
+ "version": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s="
+ },
+ "spdx-correct": {
+ "version": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
+ "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
+ "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=",
+ "dev": true
+ },
+ "spdx-license-ids": {
+ "version": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
+ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=",
+ "dev": true
+ },
+ "sprintf-js": {
+ "version": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ },
+ "sshpk": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
+ "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "statuses": {
+ "version": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
+ },
+ "stream-buffers": {
+ "version": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz",
+ "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.0.tgz",
+ "integrity": "sha1-8G9BFXtmTYYGn4S9vcmw2KsoFmc=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+ "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
+ "dev": true,
+ "optional": true
+ },
+ "strip-ansi": {
+ "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "dev": true,
+ "optional": true
+ },
+ "supports-color": {
+ "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "tar": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
+ "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
+ "dev": true
+ },
+ "tar-pack": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz",
+ "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "rimraf": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
+ "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "tar-stream": {
+ "version": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.2.tgz",
+ "integrity": "sha1-+8bG6DwaGdTLSMfZYXH8JI7/x78=",
+ "dev": true
+ },
+ "text-encoding": {
+ "version": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz",
+ "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=",
+ "dev": true
+ },
+ "through2": {
+ "version": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+ "dev": true
+ },
+ "tiny-lr": {
+ "version": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz",
+ "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=",
+ "dev": true,
+ "dependencies": {
+ "body-parser": {
+ "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz",
+ "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=",
+ "dev": true,
+ "dependencies": {
+ "qs": {
+ "version": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz",
+ "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=",
+ "dev": true
+ }
+ }
+ },
+ "bytes": {
+ "version": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz",
+ "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=",
+ "dev": true
+ },
+ "debug": {
+ "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+ "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz",
+ "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=",
+ "dev": true
+ },
+ "iconv-lite": {
+ "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
+ "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=",
+ "dev": true
+ },
+ "ms": {
+ "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+ "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
+ "dev": true
+ },
+ "qs": {
+ "version": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz",
+ "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz",
+ "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=",
+ "dev": true,
+ "dependencies": {
+ "bytes": {
+ "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
+ "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "tough-cookie": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
+ "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=",
+ "dev": true,
+ "optional": true
+ },
+ "transformers": {
+ "version": "https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz",
+ "integrity": "sha1-XSPLNVYd2F3Gf7hIIwm0fVPM6ac=",
+ "dependencies": {
+ "is-promise": {
+ "version": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz",
+ "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU="
+ },
+ "promise": {
+ "version": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz",
+ "integrity": "sha1-RmSKqdYFr10ucMMCS/WUNtoCuA4="
+ },
+ "source-map": {
+ "version": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
+ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y="
+ },
+ "uglify-js": {
+ "version": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz",
+ "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc="
+ }
+ }
+ },
+ "trim-newlines": {
+ "version": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "optional": true
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true,
+ "optional": true
+ },
+ "type-detect": {
+ "version": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz",
+ "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=",
+ "dev": true
+ },
+ "type-is": {
+ "version": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
+ "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA="
+ },
+ "typedarray": {
+ "version": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "dev": true
+ },
+ "uglify-js": {
+ "version": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.22.tgz",
+ "integrity": "sha1-1Uk0d4qNoUkD+imjJvskwKtRoaA=",
+ "dependencies": {
+ "source-map": {
+ "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
+ }
+ }
+ },
+ "uglify-to-browserify": {
+ "version": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
+ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
+ "optional": true
+ },
+ "uid-number": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz",
+ "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=",
+ "dev": true,
+ "optional": true
+ },
+ "uid-safe": {
+ "version": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz",
+ "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE="
+ },
+ "underscore": {
+ "version": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
+ "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
+ },
+ "underscore.inflections": {
+ "version": "https://registry.npmjs.org/underscore.inflections/-/underscore.inflections-0.2.1.tgz",
+ "integrity": "sha1-EBvTWeAq8pOqWhBidI6WPiCHZ/E="
+ },
+ "underscore.string": {
+ "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz",
+ "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s="
+ },
+ "unpipe": {
+ "version": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "uri-path": {
+ "version": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz",
+ "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "utils-merge": {
+ "version": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz",
+ "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg="
+ },
+ "uuid": {
+ "version": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",
+ "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=",
+ "dev": true,
+ "optional": true
+ },
+ "validate-npm-package-license": {
+ "version": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
+ "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
+ "dev": true
+ },
+ "vary": {
+ "version": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz",
+ "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc="
+ },
+ "verror": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz",
+ "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=",
+ "dev": true,
+ "optional": true
+ },
+ "void-elements": {
+ "version": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
+ "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
+ },
+ "walkdir": {
+ "version": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz",
+ "integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=",
+ "dev": true
+ },
+ "websocket-driver": {
+ "version": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz",
+ "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=",
+ "dev": true
+ },
+ "websocket-extensions": {
+ "version": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz",
+ "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=",
+ "dev": true
+ },
+ "when": {
+ "version": "https://registry.npmjs.org/when/-/when-3.7.8.tgz",
+ "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I="
+ },
+ "which": {
+ "version": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
+ "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=",
+ "dev": true
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
+ "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
+ "dev": true,
+ "optional": true
+ },
+ "window-size": {
+ "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
+ },
+ "with": {
+ "version": "https://registry.npmjs.org/with/-/with-4.0.3.tgz",
+ "integrity": "sha1-7v0VTp550sjTQXtkeo8U2f7M4U4=",
+ "dependencies": {
+ "acorn": {
+ "version": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz",
+ "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ="
+ }
+ }
+ },
+ "wordwrap": {
+ "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
+ },
+ "wrappy": {
+ "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "xtend": {
+ "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+ "dependencies": {
+ "camelcase": {
+ "version": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
+ }
+ }
+ },
+ "zip-stream": {
+ "version": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.1.1.tgz",
+ "integrity": "sha1-Uha0i7tNJlH2TVxubwnrSnOZ1Vc=",
+ "dev": true,
+ "dependencies": {
+ "lodash": {
+ "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+ "dev": true
+ }
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
index 5f8a79fb1..b62a407e2 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
"body-parser": "1.17.1",
"client-sessions": "0.8.0",
"cookie-parser": "1.4.3",
- "crafting-guide-common": ">=3.0.0 <4.0.0",
+ "crafting-guide-common": ">=5.0.0",
"dotenv": "4.0.0",
"express": "4.15.2",
"express-session": "1.15.2",
diff --git a/src/client/client.coffee b/src/client/client.coffee
index 9c7bbc064..ebf5d2286 100644
--- a/src/client/client.coffee
+++ b/src/client/client.coffee
@@ -8,77 +8,86 @@
############################################################################################################
# Allow Node.js-style `global` in addition to `window`
-if typeof(global) is 'undefined'
+if typeof(global) is "undefined"
window.global = window
-global._ = require '../common/underscore'
-global.$ = require 'jquery'
-global.c = require '../common/constants'
+global._ = require "../common/underscore"
+global.$ = require "jquery"
+global.c = require "../common/constants"
global.π = Math.PI
global.ε = 0.0001
-global.w = require 'when'
+global.w = require "when"
-{Logger} = require('crafting-guide-common').util
+{Logger} = require("crafting-guide-common").util
global.logger = new Logger
-Tracker = require './tracker'
+Tracker = require "./tracker"
global.tracker = new Tracker
-marked = require 'marked'
+marked = require "marked"
marked.setOptions sanitize:true
-global.Backbone = Backbone = require 'backbone'
+global.Backbone = Backbone = require "backbone"
Backbone.$ = $
########################################################################################################################
global.hostName = window.location.hostname
switch global.hostName
- when 'prerender.crafting-guide.com'
- global.env = 'prerender'
+ when "prerender.crafting-guide.com"
+ global.env = "prerender"
logger.level = Logger.FATAL
- apiBaseUrl = 'http://prerender.crafting-guide.com:4347'
- when 'local.crafting-guide.com', 'localhost'
- global.env = 'local'
+ apiBaseUrl = "http://prerender.crafting-guide.com:4347"
+ when "local.crafting-guide.com", "localhost"
+ global.env = "local"
logger.level = Logger.DEBUG
apiBaseUrl = "http://#{global.hostName}:4347"
- when 'staging.crafting-guide.com'
- global.env = 'staging'
+ when "staging.crafting-guide.com"
+ global.env = "staging"
logger.level = Logger.VERBOSE
- apiBaseUrl = 'http://api-staging.crafting-guide.com'
- when 'crafting-guide.com'
- global.env = 'production'
+ apiBaseUrl = "http://api-staging.crafting-guide.com"
+ when "crafting-guide.com"
+ global.env = "production"
logger.level = Logger.INFO
tracker.enabled = true
- apiBaseUrl = 'http://api.crafting-guide.com'
+ apiBaseUrl = "http://api.crafting-guide.com"
else
throw new Error "cannot determine the environment of: #{window.location.hostname}"
########################################################################################################################
-Storage = require './storage'
+Storage = require "./storage"
storage = new Storage storage:global.localStorage
########################################################################################################################
tracker.trackPageView()
-{CraftingGuideClient} = require('crafting-guide-common').api
+{CraftingGuideClient} = require("crafting-guide-common").api
client = _(new CraftingGuideClient(baseUrl:apiBaseUrl)).extend Backbone.Events
client.onStatusChanged = (client, oldStatus, newStatus)->
logger.info "Crafting Guide server status changed from #{oldStatus} to #{newStatus}"
- client.trigger 'change:status', client, oldStatus, newStatus
- client.trigger 'change', client
+ client.trigger "change:status", client, oldStatus, newStatus
+ client.trigger "change", client
client.startMonitoringStatus()
########################################################################################################################
-SiteController = require './site/site_controller'
-global.site = site = new SiteController client:client, storage:storage
-site.render()
-site.loadDefaultModPack()
-site.loadCurrentUser()
+{http, ModPackStore, ItemDetailStore} = require("crafting-guide-common").api
+storeOptions = http:http, baseUrl:"#{location.protocol}//#{location.hostname}:#{location.port}"
+global.stores =
+ modPack: new ModPackStore storeOptions
+ itemDetail: new ItemDetailStore storeOptions
-Backbone.history.start pushState:true
-logger.info -> "CraftingGuide is ready"
+########################################################################################################################
+
+global.stores.modPack.load c.modPacks.default
+ .then (modPack)->
+ SiteController = require "./site/site_controller"
+ global.site = site = new SiteController client:client, storage:storage, modPack:modPack
+ site.render()
+ site.loadCurrentUser()
+
+ Backbone.history.start pushState:true
+ logger.info -> "CraftingGuide is ready"
diff --git a/src/client/models/site/craft_page.coffee b/src/client/models/site/craft_page.coffee
index 4f2325d41..30c2b0c1d 100644
--- a/src/client/models/site/craft_page.coffee
+++ b/src/client/models/site/craft_page.coffee
@@ -5,45 +5,90 @@
# All rights reserved.
#
-CraftingGuideCommon = require "crafting-guide-common"
-
-{BaseModel} = CraftingGuideCommon.deprecated
-{Craftsman} = CraftingGuideCommon.deprecated.crafting
-{Inventory} = CraftingGuideCommon.deprecated.game
-{ModPack} = CraftingGuideCommon.deprecated.game
+{Inventory} = require("crafting-guide-common").models
+{Observable} = require("crafting-guide-common").util
+{PlanBuilder} = require("crafting-guide-common").crafting
+{ResourcesEvaluator} = require("crafting-guide-common").crafting
+{StepsEvaluator} = require("crafting-guide-common").crafting
########################################################################################################################
-module.exports = class CraftPage extends BaseModel
+module.exports = class CraftPage extends Observable
- constructor: (attributes={}, options={})->
- if not attributes.modPack then throw new Error 'attributes.modPack is required'
- attributes.params ?= null
- attributes.craftsman ?= new Craftsman attributes.modPack
- super attributes, options
+ constructor: (attributes={})->
+ super
- @modPack.on c.event.change, => @_consumeParams()
- @on c.event.change + ':params', => @_consumeParams()
- @craftsman.on c.event.change + ':stage', => @trigger c.event.change, this
- @craftsman.on c.event.change + ':complete', => @trigger c.event.change, this
+ @muted -> @modPack = attributes.modPack
+
+ @_currentPlan = null
+ @_have = new Inventory
+ @_planBuilder = new PlanBuilder new StepsEvaluator
+ @_want = new Inventory
+
+ @_consumeParams attributes.params
+
+ @_have.on Observable::ANY, this, "_onHaveChanged"
+ @_want.on Observable::ANY, this, "_onWantChanged"
+
+ # Properties ###################################################################################
+
+ Object.defineProperties @prototype,
+
+ currentPlan:
+ get: -> return @_currentPlan
+ set: -> throw new Error "currentPlan cannot be assigned"
+
+ have:
+ get: -> return @_have
+ set: -> throw new "have cannot be assigned"
+
+ isDirty:
+ get: -> return @_isDirty
+ set: -> throw new Error "isDirty cannot be assigned"
+
+ isOutdated:
+ get: -> return @currentPlan? and @isDirty
+ set: -> throw new Error "isOutdated cannot be assigned"
+
+ modPack:
+ get: -> return @_modPack
+ set: (modPack)->
+ if @_modPack? then throw new Error "modPack cannot be reassigned"
+ if not modPack? then throw new Error "modPack is required"
+ @_modPack = modPack
+
+ planBuilder:
+ get: -> return @_planBuilder
+ set: -> throw new Error "planBuilder cannot be assigned"
+
+ want:
+ get: -> return @_want
+ set: -> throw new Error "want cannot be assigned"
+
+ # Public Methods ###############################################################################
+
+ createPlan: ->
+ newPlan = @_planBuilder.createPlan @_want, @_have
+ @triggerPropertyChange "currentPlan", @_currentPlan, newPlan, ->
+ @_currentPlan = newPlan
+ @triggerPropertyChange "isDirty", @_isDirty, false
# Private Methods ##############################################################################
- _consumeParams: ->
- return unless @params?
+ _consumeParams: (params)->
+ return unless params?.inventoryText?
- @craftsman.want.clear()
- if not @params.inventoryText?
- @params = null
- else
- inventory = new Inventory
- inventory.parse @params.inventoryText
+ newWant = Inventory.fromUrlString params.inventoryText, @modPack
+ @_want.clear()
- inventory.each (stack)=>
- item = @modPack.findItem stack.itemSlug, enableAsNeeded:true
- return unless item? and item.isCraftable
+ for itemId, stack of newWant.stacks
+ continue unless stack.item.isCraftable
+ @_want.add stack.item, stack.quantity
- @craftsman.want.add stack.itemSlug, stack.quantity
- inventory.remove stack.itemSlug
+ _onHaveChanged: ->
+ @triggerPropertyChange "isDirty", @_isDirty, true
- if inventory.isEmpty then @params = null
+ _onWantChanged: ->
+ @triggerPropertyChange "isDirty", @_isDirty, true, ->
+ @_isDirty = true
+ if @want.isEmpty then @triggerPropertyChange "currentPlan", @_currentPlan, null
diff --git a/src/client/models/site/item_display.coffee b/src/client/models/site/item_display.coffee
new file mode 100644
index 000000000..a35582e0f
--- /dev/null
+++ b/src/client/models/site/item_display.coffee
@@ -0,0 +1,62 @@
+#
+# Crafting Guide - item_display.coffee
+#
+# Copyright © 2014-2017 by Redwood Labs
+# All rights reserved.
+#
+
+_ = require "../../../common/underscore"
+c = require "../../../common/constants"
+{Inventory} = require("crafting-guide-common").models
+
+########################################################################################################################
+
+module.exports = class ItemDisplay
+
+ constructor: (item)->
+ @item = item
+
+ # Properties ###################################################################################
+
+ Object.defineProperties @prototype,
+
+ craftingUrl:
+ get: ->
+ inventory = new Inventory
+ inventory.add @item
+ c.url.crafting inventoryText:inventory.toUrlString()
+
+ iconUrl:
+ get: -> return c.url.itemIcon this
+ set: -> throw new Error "iconUrl cannot be assigned"
+
+ item:
+ get: -> return @_item
+ set: (item)->
+ if @_item? then throw new Error "item cannot be re-assigned"
+ if not item? then throw new Error "item is required"
+ @_item = item
+
+ itemSlug:
+ get: -> return _.slugify @name
+ set: -> throw new Error "slug cannot be assigned"
+
+ mod:
+ get: -> return @_item.mod
+ set: -> throw new Error "mod cannot be assigned"
+
+ modId:
+ get: -> return @_item.mod.id
+ set: -> throw new Error "modId cannot be assigned"
+
+ modUrl:
+ get: -> return c.url.mod modId:@item.mod.id
+ set: -> throw new Error "modUrl cannot be assigned"
+
+ name:
+ get: -> return @item.displayName
+ set: -> throw new Error "name cannot be assigned"
+
+ url:
+ get: -> return c.url.item this
+ set: -> throw new Error "url cannot be assigned"
diff --git a/src/client/models/site/item_page.coffee b/src/client/models/site/item_page.coffee
index c0a812bd8..88fcba6ba 100644
--- a/src/client/models/site/item_page.coffee
+++ b/src/client/models/site/item_page.coffee
@@ -5,53 +5,91 @@
# All rights reserved.
#
-{BaseModel} = require("crafting-guide-common").deprecated
+{Item} = require("crafting-guide-common").models
+ItemDisplay = require "./item_display"
+{Observable} = require("crafting-guide-common").util
########################################################################################################################
-module.exports = class ItemPage extends BaseModel
+module.exports = class ItemPage extends Observable
- constructor: (attributes={}, options={})->
- if not attributes.modPack? then throw new Error 'attributes.modPack is required'
- attributes.item ?= null
- super attributes, options
+ constructor: (item)->
+ if item.constructor isnt Item then throw new Error "item must be an Item instance"
+ @item = item
+ super
+
+ # Properties ###################################################################################
+
+ Object.defineProperties @prototype,
+
+ item:
+ get: -> return @_item
+ set: (item)->
+ if @_item? then throw new Error "item cannot be reassigned"
+ if not item? then throw new Error "item is required"
+ if @_item? then @_item.off Observable::ANY, this
+ @_item = item
+ @_item.on Observable::ANY, this, "_onItemChanged"
+
+ itemDisplay:
+ get: -> return @_itemDisplay ?= new ItemDisplay @item
+
+ mod:
+ get: -> return @_item.mod
+ set: -> throw new Error "mod cannot be assigned"
+
+ modPack:
+ get: -> return @mod.modPack
+ set: -> throw new Error "modPack cannot be assigned"
# Property Methods #############################################################################
findComponentInItems: ->
- return @_findRecipesMatching (recipe)=> recipe.requires @item.slug
-
- findSimilarItems: ->
- return null unless @item?.modVersion?
-
- result = []
- @item.modVersion.eachItemInGroup @item.group, (item)=>
- result.push item
-
- return null unless result.length > 0
- return result
+ return @_findItemsWithMatchingRecipes (recipe)=>
+ recipe.computeQuantityRequired @item
findRecipes: ->
- return @modPack.findRecipes @item?.slug, [], alwaysFromOwningMod:true
+ return (recipe for recipeId, recipe of @item.recipes)
- findToolForRecipes: ->
- return @_findRecipesMatching (recipe)=> recipe.requiresTool @item.slug
+ findSimilarItems: ->
+ group = @mod.itemGroups[@item.groupName]
+ return unless group?
+
+ return null unless group.length > 0
+ return group
+
+ findToolForItems: ->
+ return @_findItemsWithMatchingRecipes (recipe)=>
+ return recipe.tools[@item.id]?
+
+ loadDetails: ->
+ stores.itemDetail.loadDetailFor @item
+ .catch (error)=>
+ if error.message.indexOf("404") is -1
+ logger.error "Could not load details for item #{@item.id}: #{error.message}"
+ else
+ logger.info "Item #{@item.id} has no details file."
# Private Methods ##############################################################################
- _findRecipesMatching: (isAcceptable)->
- return null unless @item?
-
+ _findItemsWithMatchingRecipes: (isMatching)->
result = {}
- @modPack.eachMod (mod)=>
- mod.eachRecipe (recipe)=>
- if isAcceptable recipe
- for outputStack in recipe.output
- continue if recipe.isPassThroughFor outputStack.itemSlug
- outputItem = @modPack.findItem outputStack.itemSlug, includeDisabled:true
- result[outputItem.slug] = outputItem
- result = _.values result
- return null unless result.length > 0
+ for modId, mod of @modPack.mods
+ for itemId, item of mod.items
+ for recipeId, recipe of item.recipes
+ if isMatching(recipe)
+ result[item.id] = item
+
+ result = (item for itemId, item of result)
+ result.sort (a, b)->
+ if not a?.displayName? and not b?.displayName? then return 0
+ if not b?.displayName? then return +1
+ if not a?.displayName? then return +1
+ return a.displayName.localeCompare b.displayName
+
+ return result
+
+ _onItemChanged: ->
+ @trigger Observable::CHANGE
- return result.sort (a, b)-> a.compareTo b
diff --git a/src/client/models/site/item_selector.coffee b/src/client/models/site/item_selector.coffee
index 2c4f8beb9..7e77ee3c0 100644
--- a/src/client/models/site/item_selector.coffee
+++ b/src/client/models/site/item_selector.coffee
@@ -5,52 +5,49 @@
# All rights reserved.
#
-{BaseModel} = require('crafting-guide-common').deprecated
-{ItemSlug} = require('crafting-guide-common').deprecated.game
+{Observable} = require("crafting-guide-common").util
########################################################################################################################
-module.exports = class ItemSelector extends BaseModel
+module.exports = class ItemSelector extends Observable
- constructor: (attributes={}, options={})->
- if not options.modPack? then throw new Error 'options.modPack is required'
- options.isAcceptable ?= (item)-> return true # accept everything by default
- super attributes, options
+ constructor: (modPack, options={})->
+ super
- @_isAcceptable = options.isAcceptable
+ @_isAcceptable = options.isAcceptable or (item)-> return true # accept everything by default
@_maxResults = 100
@_minHintLength = 3
- @_modPack = options.modPack
@_results = []
+ @modPack = modPack
+
# Property Methods #############################################################################
Object.defineProperties @prototype,
hint:
- get: ->
- return @_hint
+ get: -> return @_hint
+ set: (hint)->
+ @triggerPropertyChange "hint", @_hint, hint, ->
+ @_hint = hint?.toLowerCase()
+ @_refreshResults()
- set: (newHint)->
- oldHint = @_hint
- return if newHint is oldHint
-
- @_hint = newHint.toLowerCase()
-
- @trigger c.event.change + ':hint', this, oldHint, newHint
- @_refreshResults()
- @trigger c.event.change, this
+ modPack:
+ get: -> return @_modPack
+ set: (modPack)->
+ if not modPack? then throw new Error "modPack is required"
+ if @_modPack? then throw new Error "modPack cannot be reassigned"
+ @_modPack = modPack
results:
- get: ->
- return @_results
+ get: -> return @_results
# Private Methods ##############################################################################
- _computeScore: (name, itemSlug)->
+ _computeScore: (item)->
hintIndex = 0
hintLetter = @_hint[hintIndex]
- name = name.toLowerCase()
+ name = item.displayName.toLowerCase()
nextScore = 1
totalScore = 0
@@ -60,8 +57,6 @@ module.exports = class ItemSelector extends BaseModel
nextScore += 1
hintIndex += 1
if hintIndex is @_hint.length
- item = @_modPack.findItem itemSlug
- return 0 unless item?
return 0 unless @_isAcceptable item
break
@@ -70,34 +65,40 @@ module.exports = class ItemSelector extends BaseModel
nextScore = 1
return 0 if hintIndex < @_hint.length
-
- totalScore *= @_hint.length / name.length
return totalScore
_refreshResults: ->
- oldResults = @_results
scoredItems = []
count = 0
- logger.verbose => "Looking for items which match: #{@_hint}"
if @_hint.length >= @_minHintLength
- @_modPack.eachMod (mod)=>
+ for modId, mod of @_modPack.mods
return if count >= @_maxResults
- return unless mod.enabled
+ return unless mod.isEnabled
- mod.eachName (name, itemSlug)=>
- return if scoredItems.length >= @_maxResults
- return unless itemSlug.isQualified
-
- score = @_computeScore name, itemSlug
- if score >= @_hint.length
- scoredItems.push score:score, itemSlug:itemSlug
+ for itemId, item of mod.items
+ score = @_computeScore item
+ if score > 0
+ scoredItems.push score:score, item:item
scoredItems.sort (a, b)->
if a.score isnt b.score
return if a.score > b.score then -1 else +1
- return ItemSlug.compare a.itemSlug, b.itemSlug
- newResults = (e.itemSlug for e in scoredItems)
- @_results = newResults
- @trigger c.event.change + ':results', this, oldResults, newResults
+ nameA = a.item.displayName
+ nameB = b.item.displayName
+ if nameA.length isnt nameB.length
+ return if nameA.length < nameB.length then -1 else +1
+
+ if nameA isnt nameB
+ return if nameA < nameB then -1 else +1
+
+ return 0
+
+ @_results = []
+ for element in scoredItems
+ @_results.push element.item
+ break if @_results.length >= @_maxResults
+
+ @trigger c.event.change + ':results', this
+
diff --git a/src/client/models/site/markdown_image_list.coffee b/src/client/models/site/markdown_image_list.coffee
index 42821fad3..a11755541 100644
--- a/src/client/models/site/markdown_image_list.coffee
+++ b/src/client/models/site/markdown_image_list.coffee
@@ -5,26 +5,22 @@
# All rights reserved.
#
-{BaseModel} = require('crafting-guide-common').deprecated
+{Observable} = require("crafting-guide-common").util
MarkdownImage = require './markdown_image'
########################################################################################################################
-module.exports = class MarkdownImageList extends BaseModel
+module.exports = class MarkdownImageList extends Observable
- constructor: (attributes={}, options={})->
- attributes.imageBase ?= ''
- attributes.markdownText ?= null
- super attributes, options
+ constructor: (options={})->
+ super
- @client = options.client
- @_images = {}
+ @_images = []
+ @muted =>
+ @client = options.client
+ @imageBase = options.imageBase
+ @markdownText = options.markdownText
- @on c.event.change + ':imageBase', =>
- for fileName, image of @_images
- image.path = @imageBase
-
- @on c.event.change + ':markdownText', => @_analyzeMarkdownText()
@_analyzeMarkdownText()
# Public Methods ###############################################################################
@@ -46,22 +42,43 @@ module.exports = class MarkdownImageList extends BaseModel
# Property Methods #############################################################################
- getAll: ->
- fileNames = (fileName for fileName, image of @_images).sort()
- result = []
- for fileName in fileNames
- result.push @_images[fileName]
-
- return result
-
- isValid: ->
- for fileName, image of @_images
- return false unless image.valid
- return true
-
Object.defineProperties @prototype,
- all: {get:@prototype.getAll}
- valid: {get:@prototype.isValid}
+
+ all:
+ get: ->
+ fileNames = (fileName for fileName, image of @_images).sort()
+ result = []
+ for fileName in fileNames
+ result.push @_images[fileName]
+
+ return result
+
+ client:
+ get: -> return @_client
+ set: (client)->
+ if not client? then throw new Error "client is required"
+ @_client = client
+
+ imageBase: ->
+ get: -> return @_imageBase
+ set: (imageBase)->
+ @triggerPropertyChange "imageBase", @_imageBase, imageBase, ->
+ @_imageBase = imageBase
+ for fileName, image of @_images
+ image.path = @imageBase
+
+ markdownText:
+ get: -> return @_markdownText
+ set: (markdownText)->
+ @triggerPropertyChange "markdownText", @_markdownText, markdownText, ->
+ @_markdownText = markdownText
+ @_analyzeMarkdownText()
+
+ valid:
+ get: ->
+ for fileName, image of @_images
+ return false unless image.valid
+ return true
# Private Methods ##############################################################################
@@ -79,8 +96,8 @@ module.exports = class MarkdownImageList extends BaseModel
image = @_images[fileName]
if not image?
image = new MarkdownImage {fileName:fileName, path:@imageBase}, {client:@client}
- @listenTo image, c.event.change, => @trigger c.event.change, this
- @trigger c.event.add, this, image
+ image.on Observable::CHANGE, this, "_onImageChanged"
+ @trigger Observable::ADD, image
changed = true
newImages[fileName] = image
@@ -92,4 +109,7 @@ module.exports = class MarkdownImageList extends BaseModel
if changed
@_images = newImages
- @trigger c.event.change, this
+ @trigger Observable::CHANGE
+
+ _onImageChanged: ->
+ @trigger Observable::CHANGE
diff --git a/src/client/models/site/markdown_image_list.test.coffee b/src/client/models/site/markdown_image_list.test.coffee
index 58e458766..2bc701570 100644
--- a/src/client/models/site/markdown_image_list.test.coffee
+++ b/src/client/models/site/markdown_image_list.test.coffee
@@ -16,7 +16,7 @@ list = null
describe 'markdown_image_list.coffee', ->
beforeEach ->
- list = new MarkdownImageList {}, client:{fetchFile:sinon.stub().returns(w.promise(->))}
+ list = new MarkdownImageList client:{fetchFile:sinon.stub().returns(w.promise(->))}
describe '_analyzeMarkdownText', ->
diff --git a/src/client/models/site/multiblock_display.coffee b/src/client/models/site/multiblock_display.coffee
new file mode 100644
index 000000000..64df5b37d
--- /dev/null
+++ b/src/client/models/site/multiblock_display.coffee
@@ -0,0 +1,53 @@
+#
+# Crafting Guide - multiblock_display.coffee
+#
+# Copyright © 2014-2017 by Redwood Labs
+# All rights reserved.
+#
+
+{Inventory} = require("crafting-guide-common").models
+{Observable} = require("crafting-guide-common").util
+
+########################################################################################################################
+
+module.exports = class MultiblockDisplay extends Observable
+
+ constructor: (recipe)->
+ @_layerInventories = []
+ @recipe = recipe
+
+ # Properties ###################################################################################
+
+ Object.defineProperties @prototype,
+
+ recipe:
+ get: -> return @_recipe
+ set: (recipe)->
+ if not recipe? then throw new Error "recipe is required"
+ if @_recipe? then throw new Error "recipe cannot be reassigned"
+ @_recipe = recipe
+
+ # Public Methods ###############################################################################
+
+ getInventory: (z)->
+ if not z?
+ return @_fullInventory ?= @_createFullInventory()
+ else
+ return @_layerInventories[z] ?= @_addLayerInventory z
+
+ # Private Methods ##############################################################################
+
+ _addLayerInventory: (z, inventory=null)->
+ inventory ?= new Inventory
+ for x in [0..@recipe.width]
+ for y in [0..@recipe.height]
+ stack = @recipe.getInputAt x, y, z
+ continue unless stack?
+ inventory.add stack.item, stack.quantity
+ return inventory
+
+ _createFullInventory: (inventory=null)->
+ inventory ?= new Inventory()
+ for z in [0..@recipe.depth]
+ @_addLayerInventory z, inventory
+ return inventory
diff --git a/src/client/models/site/recipe_display.coffee b/src/client/models/site/recipe_display.coffee
new file mode 100644
index 000000000..b7a0a56f0
--- /dev/null
+++ b/src/client/models/site/recipe_display.coffee
@@ -0,0 +1,134 @@
+#
+# Crafting Guide - recipe_display.coffee
+#
+# Copyright © 2014-2017 by Redwood Labs
+# All rights reserved.
+#
+
+_ = require "../../../common/underscore"
+c = require "../../../common/constants"
+{Inventory} = require("crafting-guide-common").models
+{Observable} = require("crafting-guide-common").util
+
+########################################################################################################################
+
+module.exports = class RecipeDisplay extends Observable
+
+ constructor: (options={})->
+ if not options.recipe? then throw new Error "options.recipe is required"
+ super
+
+ @_layerInventories = []
+
+ @multiplier = options.multiplier or 1
+ @recipe = options.recipe
+ @showInputInventory = if options.showInputInventory then options.showInputInventory or false
+ @showOutputInventory = if options.showOutputInventory then options.showOutputInventory or false
+ @showOutputSlot = if options.showOutputSlot then options.showOutputSlot or false
+
+ # Class Methods ################################################################################
+
+ @::RECIPE_TYPE =
+ CRAFTING_TABLE: "crafting_table"
+ MULTIBLOCK: "multiblock"
+
+ @::ALL_RECIPE_TYPES = (value for key, value of @::RECIPE_TYPE)
+
+ # Properties ###################################################################################
+
+ Object.defineProperties @prototype,
+
+ depth:
+ get: -> return @recipe.depth
+ set: -> throw new Error "depth cannot be assigned"
+
+ height:
+ get: -> return @recipe.height
+ set: -> throw new Error "height cannot be assigned"
+
+ multiplier:
+ get: -> return @_multiplier
+ set: (multiplier)->
+ if not _.isNumber(multiplier) then multiplier = 1
+ @triggerPropertyChange "multiplier", @_multiplier, multiplier
+
+ recipe:
+ get: -> return @_recipe
+ set: (recipe)->
+ return if recipe is @_recipe
+ if not recipe? then throw new Error "recipe is required"
+ if @_recipe? then throw new Error "recipe cannot be reassigned"
+ @_recipe = recipe
+ @_computeType()
+
+ showInputInventory:
+ get: -> return @_showInputInventory
+ set: (showInputInventory)->
+ @triggerPropertyChange "showInputInventory", @_showInputInventory, !!showInputInventory
+
+ showOutputInventory:
+ get: -> return @_showOutputInventory
+ set: (showOutputInventory)->
+ @triggerPropertyChange "showOutputInventory", @_showOutputInventory, !!showOutputInventory
+
+ showOutputSlot:
+ get: -> return @_showOutputSlot
+ set: (showOutputSlot)->
+ @triggerPropertyChange "showOutputSlot", @_showOutputSlot, !!showOutputSlot
+
+ tools:
+ get: -> return @recipe.tools
+ set: -> throw new Error "tools cannot be assigned"
+
+ type:
+ get: -> return @_type
+ set: -> throw new Error "type cannot be assigned"
+
+ width:
+ get: -> return @recipe.width
+ set: -> throw new Error "width cannot be assigned"
+
+ # Public Methods ###############################################################################
+
+ getInputAt: (x, y, z)->
+ return @recipe.getInputAt x, y, z
+
+ getInventory: (z)->
+ if not z?
+ return @_fullInventory ?= @_createFullInventory()
+ else
+ return @_layerInventories[z] ?= @_addLayerInventory z
+
+ getOutputInventory: ->
+ if not @_outputInventory?
+ @_outputInventory = new Inventory
+ for stack in @recipe.allProducts
+ @_outputInventory.add stack.item, stack.quantity
+
+ return @_outputInventory
+
+ # Private Methods ##############################################################################
+
+ _addLayerInventory: (z, inventory=null)->
+ inventory ?= new Inventory
+ for x in [0..@recipe.width]
+ for y in [0..@recipe.height]
+ stack = @recipe.getInputAt x, y, z
+ continue unless stack?
+ inventory.add stack.item, stack.quantity * @multiplier
+ return inventory
+
+ _computeType: ->
+ if not @recipe?
+ type = null
+ else if @recipe.depth > 1
+ type = @RECIPE_TYPE.MULTIBLOCK
+ else
+ type = @RECIPE_TYPE.CRAFTING_TABLE
+ @triggerPropertyChange "type", @_type, type
+
+ _createFullInventory: (inventory=null)->
+ inventory ?= new Inventory()
+ for z in [0..@recipe.depth]
+ @_addLayerInventory z, inventory
+ return inventory
diff --git a/src/client/models/stores/mod_pack_store.coffee b/src/client/models/stores/mod_pack_store.coffee
deleted file mode 100644
index 8184c3e3d..000000000
--- a/src/client/models/stores/mod_pack_store.coffee
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# Crafting Guide - mod_pack_store.coffee
-#
-# Copyright © 2014-2017 by Redwood Labs
-# All rights reserved.
-#
-
-ModPackJsonParser = require "../parsing/mod_pack_json_parser"
-w = require "when"
-
-########################################################################################################################
-
-module.exports = class ModPackStore
-
- constructor: ->
- @_data = {}
- @_loading = {}
- @_parser = new ModPackJsonParser
-
- # Class Methods ################################################################################
-
- Object.defineProperties ModPackStore,
- instance:
- get: ->
- @_instance ?= new ModPackStore
- return @_instance
- set: ->
- throw new Error "cannot assign instance"
-
- # Public Methods ###############################################################################
-
- get: (modPackId)->
- return @_data[modPackId]
-
- load: (modPackId)->
- if not @_loading[modPackId]?
- @_loading[modPackId] = w.promise (resolve, reject)->
- url = c.url.modPackArchive modPackId:modPackId
-
- onError = (xhr, status, message)=>
- logger.error "failed to load mod pack #{modPackId}: #{status} — #{message}"
- reject new Error message
-
- onSuccess = (data, status, xhr)=>
- logger.info "laoded mod pack: #{modPackId}"
- try
- @_parser.reset()
- modPack = @_parser.parse data, url
- @_data[modPack.id] = modPack
- resolve modPack
- catch error
- reject error
-
- $.ajax dataType: "text", error: onError, success: onSuccess, url: url
-
- return @_loading[modPackId]
diff --git a/src/client/site/base_controller.coffee b/src/client/site/base_controller.coffee
index 21564d860..d1f7733f8 100644
--- a/src/client/site/base_controller.coffee
+++ b/src/client/site/base_controller.coffee
@@ -5,7 +5,8 @@
# All rights reserved.
#
-templates = require './templates'
+{Observable} = require("crafting-guide-common").util
+templates = require './templates'
########################################################################################################################
@@ -84,9 +85,6 @@ module.exports = class BaseController extends Backbone.View
onDidModelChange: ->
@tryRefresh()
- onDidModelSync: ->
- @tryRefresh()
-
onWillRender: -> # do nothing
onDidRender: -> # do nothing
@@ -96,11 +94,12 @@ module.exports = class BaseController extends Backbone.View
onDidShow: -> # do nothing
onWillChangeModel: (oldModel, newModel)->
- if oldModel?.on?
- @stopListening oldModel
- if newModel?.on?
- @listenTo newModel, 'sync', (e)=> @onDidModelSync e
- @listenTo newModel, 'change', (e)=> @onDidModelChange e
+ if oldModel?.isObservable
+ oldModel.off target:this
+
+ if newModel?.isObservable
+ newModel.on Observable::ANY, this, "onDidModelChange"
+
return newModel
# Property Methods #############################################################################
@@ -113,7 +112,7 @@ module.exports = class BaseController extends Backbone.View
newModel = @onWillChangeModel @_model, newModel
@_model = newModel
- @tryRefresh()
+ @onDidModelChange()
rendered:
get: -> @_rendered
@@ -147,9 +146,13 @@ module.exports = class BaseController extends Backbone.View
@$el.append $renderedEl.children()
@$el.addClass $renderedEl.attr 'class'
- @$el.data $renderedEl.data()
- @delegateEvents()
+ elementData = $renderedEl.data()
+ elementData.controller = this
+ elementData.model = data
+ @$el.data elementData
+
+ @delegateEvents()
@_rendered = true
@onDidRender()
diff --git a/src/client/site/browse_page/browse_page_controller.coffee b/src/client/site/browse_page/browse_page_controller.coffee
index 7baa67088..28c8a648a 100644
--- a/src/client/site/browse_page/browse_page_controller.coffee
+++ b/src/client/site/browse_page/browse_page_controller.coffee
@@ -28,7 +28,6 @@ module.exports = class BrowsePageController extends PageController
@_tileControllers = []
@_client.on c.event.change, => @tryRefresh()
- @_modPack.on c.event.change, => @tryRefresh()
# Property Methods #############################################################################
@@ -81,7 +80,7 @@ module.exports = class BrowsePageController extends PageController
_refreshModTiles: ->
index = 0
- mods = @_modPack.getAllMods()
+ mods = (mod for modId, mod of @_modPack.mods)
for mod in mods
controller = @_tileControllers[index]
if not controller
diff --git a/src/client/site/browse_page/mod_tile/mod_tile_controller.coffee b/src/client/site/browse_page/mod_tile/mod_tile_controller.coffee
index ecb42f375..9c3fe8640 100644
--- a/src/client/site/browse_page/mod_tile/mod_tile_controller.coffee
+++ b/src/client/site/browse_page/mod_tile/mod_tile_controller.coffee
@@ -29,12 +29,12 @@ module.exports = class ModTileController extends BaseController
super
refresh: ->
- @$link.attr 'href', c.url.mod modSlug:@model.slug
- @$logoImage.attr 'src', c.url.modIcon modSlug:@model.slug
- @$title.text @model.name
+ @$link.attr 'href', c.url.mod modId:@model.id
+ @$logoImage.attr 'src', c.url.modIcon modId:@model.id
+ @$title.text @model.displayName
@$description.text @model.description
- if @model.enabled
+ if @model.isEnabled
@$el.removeClass 'disabled'
else
@$el.addClass 'disabled'
diff --git a/src/client/site/common/crafting_grid/crafting_grid_controller.coffee b/src/client/site/common/crafting_grid/crafting_grid_controller.coffee
index ab87389b9..53a22709c 100644
--- a/src/client/site/common/crafting_grid/crafting_grid_controller.coffee
+++ b/src/client/site/common/crafting_grid/crafting_grid_controller.coffee
@@ -5,39 +5,47 @@
# All rights reserved.
#
-BaseController = require '../../base_controller'
-SlotController = require '../slot/slot_controller'
+BaseController = require "../../base_controller"
+{Recipe} = require("crafting-guide-common").models
+SlotController = require "../slot/slot_controller"
########################################################################################################################
module.exports = class CraftingGridController extends BaseController
constructor: (options={})->
- if not options.imageLoader? then throw new Error 'options.imageLoader is required'
- if not options.modPack? then throw new Error 'options.modPack is required'
- if not options.router? then throw new Error 'options.router is required'
- # options.model should be a recipe
- options.templateName = 'common/crafting_grid'
+ if not options.imageLoader? then throw new Error "options.imageLoader is required"
+ if not options.modPack? then throw new Error "options.modPack is required"
+ if not options.router? then throw new Error "options.router is required"
+ options.templateName = "common/crafting_grid"
super options
@_imageLoader = options.imageLoader
@_modPack = options.modPack
@_router = options.router
- @_modPack.on c.event.change, => @tryRefresh()
-
# BaseController Methods #######################################################################
+ onWillChangeModel: (oldModel, newModel)->
+ if newModel? and (newModel.constructor isnt Recipe) then throw new Error "options.model must be a Recipe"
+ super
+
onDidRender: ->
@_slotControllers = []
- for el in @$('.view__slot')
+ for el in @$(".view__slot")
controller = new SlotController el:el, imageLoader:@_imageLoader, modPack:@_modPack, router:@_router
controller.render()
@_slotControllers.push controller
super
refresh: ->
- for controller, index in @_slotControllers
- controller.model = @model?.getStackAtSlot(index)
+ index = 0
+ for y in [0..2]
+ for x in [0..2]
+ controller = @_slotControllers[index++]
+ if @model?
+ controller.model = @model.getInputAt x, y
+ else
+ controller.model = null
super
diff --git a/src/client/site/common/inventory/inventory_controller.coffee b/src/client/site/common/inventory/inventory_controller.coffee
index 9e2e4fe11..1110080b1 100644
--- a/src/client/site/common/inventory/inventory_controller.coffee
+++ b/src/client/site/common/inventory/inventory_controller.coffee
@@ -47,8 +47,6 @@ module.exports = class InventoryController extends BaseController
@_stackControllers = []
- @listenTo @_modPack, c.event.change, => @tryRefresh()
-
# Event Methods ################################################################################
onClearButtonClicked: ->
@@ -61,31 +59,33 @@ module.exports = class InventoryController extends BaseController
@trigger c.event.change, this
onFirstButtonClicked: (stackController)->
- tracker.trackEvent @_trackingContext, 'remove-from', "#{stackController?.model?.itemSlug}"
- @trigger c.event.button.first, this, stackController?.model?.itemSlug
+ item = stackController.model?.item
+ tracker.trackEvent @_trackingContext, 'remove-from', item.id
+ @trigger c.event.button.first, this, item
onItemSelectorButtonClicked: ->
return unless @model?
tracker.trackEvent @_trackingContext, 'launch-add-to'
@_selector.launch()
- .then (itemSlug)=>
- if not itemSlug?
+ .then (item)=>
+ if not item?
tracker.trackEvent @_trackingContext, 'cancel-add-to'
return
- tracker.trackEvent @_trackingContext, 'complete-add-to', "#{itemSlug}"
- @model.add itemSlug, 1
- @trigger c.event.add, this, itemSlug
+ tracker.trackEvent @_trackingContext, 'complete-add-to', "#{item.id}"
+ @model.add item, 1
+ @trigger c.event.add, this, item.id
@trigger c.event.change, this
onSecondButtonClicked: (stackController)->
+ itemId = stackController.model?.item.id
@trigger c.event.button.second, this, stackController?.model?.itemSlug
# BaseController Overrides #####################################################################
onDidRender: ->
- @_selector = @addChild ItemSelectorController, null, isAcceptable: @_isAcceptable, modPack: @_modPack
+ @_selector = @addChild ItemSelectorController, null, isAcceptable:@_isAcceptable, modPack:@_modPack
@$clearButton = @$('.button.clear')
@$emptyPlaceholder = @$('.empty_placeholder')
@@ -131,7 +131,7 @@ module.exports = class InventoryController extends BaseController
index = 0
if @model?
- @model.each (stack)=>
+ for itemId, stack of @model.stacks
controller = @_stackControllers[index]
if not controller?
controller = new StackController
@@ -153,7 +153,9 @@ module.exports = class InventoryController extends BaseController
@$itemContainer.append controller.$el
else
controller.model = stack
+
index += 1
while @_stackControllers.length > index
@_stackControllers.pop().remove()
+
diff --git a/src/client/site/common/item_group/item_tile/item_tile_controller.coffee b/src/client/site/common/item_group/item_tile/item_tile_controller.coffee
index ad867f32e..147ed405e 100644
--- a/src/client/site/common/item_group/item_tile/item_tile_controller.coffee
+++ b/src/client/site/common/item_group/item_tile/item_tile_controller.coffee
@@ -5,39 +5,37 @@
# All rights reserved.
#
-BaseController = require '../../../base_controller'
+BaseController = require "../../../base_controller"
+ItemDisplay = require "../../../../models/site/item_display"
########################################################################################################################
module.exports = class ItemTileController extends BaseController
constructor: (options={})->
- if not options.imageLoader? then throw new Error 'options.imageLoader is required'
- if not options.model? then throw new Error 'options.model is required'
- if not options.modPack? then throw new Error 'options.modPack is required'
- options.templateName = 'common/item_group/item_tile'
+ if not options.imageLoader? then throw new Error "options.imageLoader is required"
+ if not options.model? then throw new Error "options.model is required"
+ options.templateName = "common/item_group/item_tile"
super options
@_imageLoader = options.imageLoader
- @_modPack = options.modPack
+ @_display = new ItemDisplay @model
# BaseController Overrides #####################################################################
onDidRender: ->
- @$icon = @$('img')
- @$name = @$('.itemName')
- @$nameLink = @$('a')
+ @$icon = @$("img")
+ @$name = @$(".itemName")
+ @$nameLink = @$("a")
super
refresh: ->
- display = @_modPack.findItemDisplay @model.slug
-
- @_imageLoader.load display.iconUrl, @$icon
- @$name.html display.itemName
- @$nameLink.attr 'href', display.itemUrl
+ @_imageLoader.load @_display.iconUrl, @$icon
+ @$name.html @_display.name
+ @$nameLink.attr "href", @_display.url
# Backbone.View Overrides ######################################################################
events: ->
return _.extend super,
- 'click a': 'routeLinkClick'
+ "click a": "routeLinkClick"
diff --git a/src/client/site/common/item_selector/element/element_controller.coffee b/src/client/site/common/item_selector/element/element_controller.coffee
index c1ccbe108..38dd56d6c 100644
--- a/src/client/site/common/item_selector/element/element_controller.coffee
+++ b/src/client/site/common/item_selector/element/element_controller.coffee
@@ -5,58 +5,63 @@
# All rights reserved.
#
-BaseController = require '../../../base_controller'
+BaseController = require "../../../base_controller"
+ItemDisplay = require "../../../../models/site/item_display"
########################################################################################################################
module.exports = class ElementController extends BaseController
constructor: (options={})->
- if not options.model? then throw new Error 'options.model is required'
- options.onClicked ?= (controller)-> # do nothing
- options.onSelected ?= (controller)-> # do nothing
- options.templateName = 'common/item_selector/element'
+ if not options.model? then throw new Error "options.model is required"
+ options.templateName = "common/item_selector/element"
options.useAnimations = false
super options
- @onClicked = options.onClicked
- @onSelected = options.onSelected
+ @onClicked = options.onClicked or (controller)-> # do nothing
+ @onSelected = options.onSelected or (controller)-> # do nothing
# Property Methods #############################################################################
- isSelected: ->
- return @_selected
-
- setSelected: (newSelected)->
- oldSelected = @_selected
- return if newSelected is oldSelected
-
- @_selected = newSelected
- @tryRefresh()
-
- @trigger c.event.change + ':selected', this, oldSelected, newSelected
- @trigger c.event.change, this
-
Object.defineProperties @prototype,
- selected: {get:@prototype.isSelected, set:@prototype.setSelected}
+
+ display:
+ get: -> return @_display ?= new ItemDisplay @model
+ set: -> throw new Error "display cannot be assigned"
+
+ isSelected:
+ get: -> return @_selected
+ set: (newSelected)->
+ oldSelected = @_selected
+ return if newSelected is oldSelected
+
+ @_selected = newSelected
+ @tryRefresh()
+
+ @trigger c.event.change + ":selected", this, oldSelected, newSelected
+ @trigger c.event.change, this
# BaseController Overrides #####################################################################
+ onDidModelChange: ->
+ @_display = null
+ super
+
onDidRender: ->
- @$icon = @$('img')
- @$name = @$('.name')
- @$modName = @$('.modName')
+ @$icon = @$("img")
+ @$name = @$(".name")
+ @$modName = @$(".modName")
super
refresh: ->
- @$icon.attr 'src', @model.iconUrl
- @$name.html @model.itemName
- @$modName.html @model.modName
+ @$icon.attr "src", @display.iconUrl
+ @$name.html @model.displayName
+ @$modName.html @model.mod.displayName
if @_selected
- @$el.addClass 'selected'
+ @$el.addClass "selected"
else
- @$el.removeClass 'selected'
+ @$el.removeClass "selected"
super
@@ -64,15 +69,15 @@ module.exports = class ElementController extends BaseController
events: ->
return _.extend super,
- 'click': '_onClick'
- 'mouseenter': '_onMouseEnter'
+ "click": "_onClick"
+ "mouseenter": "_onMouseEnter"
# Private Methods ##############################################################################
_onClick: (event)->
- event.preventDefault()
@onClicked this
+ return false
_onMouseEnter: (event)->
- event.preventDefault()
@onSelected this
+ return false
diff --git a/src/client/site/common/item_selector/item_selector_controller.coffee b/src/client/site/common/item_selector/item_selector_controller.coffee
index 33c634a7a..25f70433d 100644
--- a/src/client/site/common/item_selector/item_selector_controller.coffee
+++ b/src/client/site/common/item_selector/item_selector_controller.coffee
@@ -5,21 +5,22 @@
# All rights reserved.
#
-BaseController = require '../../base_controller'
-ItemSelector = require '../../../models/site/item_selector'
-ElementController = require './element/element_controller'
+BaseController = require "../../base_controller"
+ItemDisplay = require "../../../models/site/item_display"
+ItemSelector = require "../../../models/site/item_selector"
+ElementController = require "./element/element_controller"
w = require "when"
########################################################################################################################
module.exports = class ItemSelectorController extends BaseController
- constructor: (options)->
- if not options.modPack? then throw new Error 'options.modPack is required'
+ constructor: (options={})->
+ if not options.modPack? then throw new Error "options.modPack is required"
options.isAcceptable ?= null
- options.model ?= new ItemSelector {}, modPack:options.modPack, isAcceptable:options.isAcceptable
+ options.model ?= new ItemSelector options.modPack, isAcceptable:options.isAcceptable
options.onChoseItem ?= (item)-> # do nothing
- options.templateName = 'common/item_selector'
+ options.templateName = "common/item_selector"
super options
@_modPack = options.modPack
@@ -29,25 +30,25 @@ module.exports = class ItemSelectorController extends BaseController
# Public Methods ###############################################################################
- launch: (hint='')->
+ launch: (hint="")->
@model.hint = hint
if @rendered then @refresh()
@_disableWindowScrolling()
- @$page.addClass 'blur'
+ @$page.addClass "blur"
@$screen.append @$popup
- @$screen.css 'display', ''
+ @$screen.css "display", ""
@$popup.off c.event.click
@$popup.on c.event.click, (event)=> @onPopupClicked(event)
- @$hintField.off 'keyup input'
- @$hintField.on 'keyup', (event)=> @onHintKeyPress(event)
- @$hintField.on 'input', (event)=> @onHintChanged(event)
+ @$hintField.off "keyup input"
+ @$hintField.on "keyup", (event)=> @onHintKeyPress(event)
+ @$hintField.on "input", (event)=> @onHintChanged(event)
@$hintField.focus()
- @$closeButton.one 'click', (event)=> @_close()
+ @$closeButton.one "click", (event)=> @_close()
@$screen.one c.event.click, (event)=> @onScreenClicked(event)
@@ -85,17 +86,17 @@ module.exports = class ItemSelectorController extends BaseController
return false
onResultClicked: (controller)->
- @_session.resolve controller.model.slug
+ @_session.resolve controller.model
@_session = null
@_close()
return false
onResultSelected: (controller)->
for c in @_elementControllers
- c.selected = false
+ c.isSelected = false
if controller?
- controller.selected = true
+ controller.isSelected = true
return false
@@ -106,14 +107,14 @@ module.exports = class ItemSelectorController extends BaseController
# BaseController Overrides #####################################################################
onDidRender: ->
- @$page = $('.page') # find the shared, global page
- @$screen = $('.view__screen') # find the shared, global screen
+ @$page = $(".page") # find the shared, global page
+ @$screen = $(".view__screen") # find the shared, global screen
- @$closeButton = @$('img.close')
- @$popup = @$('.view__item_selector_popup')
- @$hintField = @$('.view__item_selector_popup input')
- @$searchInput = @$('.search input')
- @$resultsContainer = @$('.results')
+ @$closeButton = @$("img.close")
+ @$popup = @$(".view__item_selector_popup")
+ @$hintField = @$(".view__item_selector_popup input")
+ @$searchInput = @$(".search input")
+ @$resultsContainer = @$(".results")
@$popup.detach()
super
@@ -127,16 +128,16 @@ module.exports = class ItemSelectorController extends BaseController
_chooseSelected: ->
for controller in @_elementControllers
- if controller.selected
+ if controller.isSelected
@onResultClicked controller
return
_close: ->
@_enableWindowScrolling()
- @$page.removeClass 'blur'
- @$screen.css 'display', 'none'
+ @$page.removeClass "blur"
+ @$screen.css "display", "none"
@$popup.detach()
- @model.hint = ''
+ @model.hint = ""
if @_session
@_session.resolve null
@@ -144,28 +145,27 @@ module.exports = class ItemSelectorController extends BaseController
_disableWindowScrolling: ->
@_windowScrollPosition = $(window).scrollTop()
- $('body').addClass('scrollDisabled').css('margin-top', -@_windowScrollPosition)
+ $("body").addClass("scrollDisabled").css("margin-top", -@_windowScrollPosition)
_enableWindowScrolling: ->
- $('body').removeClass('scrollDisabled').css('margin-top', 0)
+ $("body").removeClass("scrollDisabled").css("margin-top", 0)
$(window).scrollTop @_windowScrollPosition
_refreshResults: ->
index = 0
- for itemSlug in @model.results
- displayModel = @_modPack.findItemDisplay itemSlug
+ for item in @model.results
controller = @_elementControllers[index]
if not controller?
controller = new ElementController
- model: displayModel
+ model: item
onClicked: (c)=> @onResultClicked(c)
onSelected: (c)=> @onResultSelected(c)
controller.render show:false
@_elementControllers[index] = controller
@$resultsContainer.append controller.$el
else
- controller.model = displayModel
+ controller.model = item
controller.show()
index += 1
@@ -180,14 +180,17 @@ module.exports = class ItemSelectorController extends BaseController
controller = @_elementControllers[i]
nextController = @_elementControllers[i + 1]
- if controller.selected
- controller.selected = false
- nextController.selected = true
+ if controller.isSelected
+ controller.isSelected = false
+ nextController.isSelected = true
@_showElement nextController.$el
return
+ [..., controller] = @_elementControllers
+ controller.isSelected = false
+
controller = @_elementControllers[0]
- controller.selected = true
+ controller.isSelected = true
@_showElement controller.$el
_selectPrevious: ->
@@ -197,14 +200,17 @@ module.exports = class ItemSelectorController extends BaseController
previousController = @_elementControllers[i - 1]
controller = @_elementControllers[i]
- if controller.selected
- previousController.selected = true
- controller.selected = false
+ if controller.isSelected
+ previousController.isSelected = true
+ controller.isSelected = false
@_showElement previousController.$el
return
- controller = @_elementControllers[@_elementControllers.length - 1]
- controller.selected = true
+ controller = @_elementControllers[0]
+ controller.isSelected = false
+
+ [..., controller] = @_elementControllers
+ controller.isSelected = true
@_showElement controller.$el
_showElement: ($el)->
diff --git a/src/client/site/common/markdown_section/markdown_image_list/markdown_image_list_controller.coffee b/src/client/site/common/markdown_section/markdown_image_list/markdown_image_list_controller.coffee
index 81db1a92d..d2468583d 100644
--- a/src/client/site/common/markdown_section/markdown_image_list/markdown_image_list_controller.coffee
+++ b/src/client/site/common/markdown_section/markdown_image_list/markdown_image_list_controller.coffee
@@ -5,20 +5,24 @@
# All rights reserved.
#
-BaseController = require '../../../base_controller'
-MarkdownImageController = require './markdown_image/markdown_image_controller'
-MarkdownImageList = require '../../../../models/site/markdown_image_list'
+_ = require "../../../../../underscore"
+c = require "../../../../../common/constants"
+BaseController = require "../../../base_controller"
+MarkdownImageController = require "./markdown_image/markdown_image_controller"
+MarkdownImageList = require "../../../../models/site/markdown_image_list"
+{Observable} = require("crafting-guide-common").util
########################################################################################################################
module.exports = class MarkdownImageListController extends BaseController
+ _.extend this, Observable
constructor: (options={})->
- options.model ?= new MarkdownImageList {}, {client:options.client}
- options.templateName = 'common/markdown_section/markdown_image_list'
+ options.model ?= new MarkdownImageList client:options.client
+ options.templateName = "common/markdown_section/markdown_image_list"
super options
- @imageBase = ''
+ @imageBase = ""
@_valid = null
# Public Methods ###############################################################################
@@ -33,31 +37,24 @@ module.exports = class MarkdownImageListController extends BaseController
@model.reset()
# Property Methods #############################################################################
-
- getImageBase: ->
- return @_imageBase
-
- setImageBase: (newImageBase)->
- oldImageBase = @_imageBase
- return unless oldImageBase isnt newImageBase
-
- @_imageBase = newImageBase
- @trigger c.event.change + ':imageBase', this, oldImageBase, newImageBase
- @trigger c.event.change, this
-
- getMarkdownText: ->
- return @model.markdownText
-
- setMarkdownText: (markdownText)->
- @model.markdownText = markdownText
-
- getValid: ->
- return @_valid
-
+
Object.defineProperties @prototype,
- imageBase: {get:@prototype.getImageBase, set:@prototype.setImageBase}
- markdownText: {get:@prototype.getMarkdownText, set:@prototype.setMarkdownText}
- valid: {get:@prototype.getValid}
+
+ imageBase:
+ get: -> return @_imageBase
+ set: (imageBase)->
+ @_imageBase = imageBase
+ @trigger c.event.change
+
+ markdownText:
+ get: -> return @model.markdownText
+ set: (markdownText)->
+ @model.markdownText = markdownText
+ @trigger c.event.change
+
+ valid:
+ get: -> return @_valid
+ set: -> throw new Error "valid cannot be assigned"
# BaseController Overrides #####################################################################
@@ -66,7 +63,7 @@ module.exports = class MarkdownImageListController extends BaseController
@_setValid @model.valid
onDidRender: ->
- @$imageContainer = @$('.image_container')
+ @$imageContainer = @$(".image_container")
super
refresh: ->
@@ -90,10 +87,6 @@ module.exports = class MarkdownImageListController extends BaseController
# Private Methods ##############################################################################
- _setValid: (newValid)->
- oldValid = @_valid
- return if newValid is oldValid
-
- @_valid = newValid
- @trigger c.event.change + ':valid', this, oldValid, newValid
+ _setValid: (valid)->
+ @_valid = valid
@trigger c.event.change
diff --git a/src/client/site/common/markdown_section/markdown_section_controller.coffee b/src/client/site/common/markdown_section/markdown_section_controller.coffee
index fe758d45b..0f9020ff1 100644
--- a/src/client/site/common/markdown_section/markdown_section_controller.coffee
+++ b/src/client/site/common/markdown_section/markdown_section_controller.coffee
@@ -5,27 +5,28 @@
# All rights reserved.
#
-BaseController = require '../../base_controller'
-convertMarkdown = require 'marked'
-MarkdownImageListController = require './markdown_image_list/markdown_image_list_controller'
+BaseController = require "../../base_controller"
+convertMarkdown = require "marked"
+ItemDisplay = require "../../../models/site/item_display"
+MarkdownImageListController = require "./markdown_image_list/markdown_image_list_controller"
########################################################################################################################
module.exports = class MarkdownSectionController extends BaseController
@::State =
- appologizing: 'applogizing'
- confirming: 'confirming'
- creating: 'creating'
- editing: 'editing'
- previewing: 'previewing'
- viewing: 'viewing'
- waiting: 'waiting'
+ appologizing: "applogizing"
+ confirming: "confirming"
+ creating: "creating"
+ editing: "editing"
+ previewing: "previewing"
+ viewing: "viewing"
+ waiting: "waiting"
constructor: (options={})->
- if not options.modPack? then throw new Error 'options.modPack is required'
+ if not options.modPack? then throw new Error "options.modPack is required"
options.model ?= null
- options.templateName = 'common/markdown_section'
+ options.templateName = "common/markdown_section"
@_state = @State.waiting
super options
@@ -33,9 +34,9 @@ module.exports = class MarkdownSectionController extends BaseController
@_confirmationMessage = options.confirmationMessage
@_confirmDuration = options.confirmationDuration or 5000
@_enterFeedback = options.enterFeedback or -> # do nothing
- @_imageBase = options.imageBase or ''
+ @_imageBase = options.imageBase or ""
@_modPack = options.modPack
- @_title = options.title or 'Description'
+ @_title = options.title or "Description"
# @_beginEditing must be a function returning a promise which resolves when all actions necessary prior to an
# editing session have been completed (e.g., loading the latest content from a remote server). The promise must
@@ -60,7 +61,7 @@ module.exports = class MarkdownSectionController extends BaseController
# Event Methods ################################################################################
onCancelClicked: (event)->
- tracker.trackEvent c.tracking.category.markdown, 'cancel'
+ tracker.trackEvent c.tracking.category.markdown, "cancel"
@model = @_originalModel
@resetToDefaultState()
@@ -71,7 +72,7 @@ module.exports = class MarkdownSectionController extends BaseController
onEditClicked: (event)->
return false unless @editable
- tracker.trackEvent c.tracking.category.markdown, 'edit'
+ tracker.trackEvent c.tracking.category.markdown, "edit"
@_originalModel = @model
@state = @State.waiting
@_beginEditing()
@@ -85,22 +86,22 @@ module.exports = class MarkdownSectionController extends BaseController
return false
onQuestionClicked: (event)->
- @_enterFeedback ''
+ @_enterFeedback ""
return false
onPreviewClicked: (event)->
- tracker.trackEvent c.tracking.category.markdown, 'preview'
+ tracker.trackEvent c.tracking.category.markdown, "preview"
@_updatePreview()
@state = @State.previewing
return false
onReturnClicked: (event)->
- tracker.trackEvent c.tracking.category.markdown, 'return'
+ tracker.trackEvent c.tracking.category.markdown, "return"
@state = @State.editing
return false
onSaveClicked: (event)->
- tracker.trackEvent c.tracking.category.markdown, 'save'
+ tracker.trackEvent c.tracking.category.markdown, "save"
@state = @State.waiting
@_endEditing()
.then =>
@@ -132,7 +133,7 @@ module.exports = class MarkdownSectionController extends BaseController
return unless newImageBase isnt oldImageBase
@_imageBase = newImageBase
- @trigger c.event.change + ':imageBase', this, oldImageBase, newImageBase
+ @trigger c.event.change + ":imageBase", this, oldImageBase, newImageBase
@trigger c.event.change, this
getImageFiles: ->
@@ -147,7 +148,7 @@ module.exports = class MarkdownSectionController extends BaseController
@_state = newState
logger.verbose => "MarkdownSectionController.#{@cid} changed state from #{oldState} to #{newState}"
- @trigger c.event.change + ':state', this, oldState, newState
+ @trigger c.event.change + ":state", this, oldState, newState
@tryRefresh()
Object.defineProperties @prototype,
@@ -159,21 +160,21 @@ module.exports = class MarkdownSectionController extends BaseController
# BaseController Overrides #####################################################################
onDidRender: ->
- @_imageListController = @addChild MarkdownImageListController, '.view__markdown_image_list',
+ @_imageListController = @addChild MarkdownImageListController, ".view__markdown_image_list",
client: @_client
imageBase: @_imageBase
- @on c.event.change + ':imageBase', => @_imageListController.model.imageBase = @_imageBase
- @listenTo @_imageListController, c.event.change + ':valid', => @tryRefresh()
+ @on c.event.change + ":imageBase", => @_imageListController.model.imageBase = @_imageBase
+ @listenTo @_imageListController, c.event.change + ":valid", => @tryRefresh()
- @$errorPanel = @$('.error')
- @$errorText = @$('.error p')
- @$markdownPanel = @$('.markdown')
- @$previewButton = @$('.button.preview')
- @$questionPanel = @$('.question')
- @$saveButton = @$('.button.save')
- @$sizer = @$('.sizer')
- @$textarea = @$('textarea')
- @$title = @$('h2')
+ @$errorPanel = @$(".error")
+ @$errorText = @$(".error p")
+ @$markdownPanel = @$(".markdown")
+ @$previewButton = @$(".button.preview")
+ @$questionPanel = @$(".question")
+ @$saveButton = @$(".button.save")
+ @$sizer = @$(".sizer")
+ @$textarea = @$("textarea")
+ @$title = @$("h2")
@resetToDefaultState()
@@ -199,14 +200,14 @@ module.exports = class MarkdownSectionController extends BaseController
events: ->
return _.extend super,
- 'click .markdown a': 'routeLinkClick'
- 'click .button.cancel': 'onCancelClicked'
- 'click .button.edit': 'onEditClicked'
- 'click .button.preview': 'onPreviewClicked'
- 'click .button.return': 'onReturnClicked'
- 'click .button.save': 'onSaveClicked'
- 'click .question a': 'onQuestionClicked'
- 'input textarea': 'onTextChanged'
+ "click .markdown a": "routeLinkClick"
+ "click .button.cancel": "onCancelClicked"
+ "click .button.edit": "onEditClicked"
+ "click .button.preview": "onPreviewClicked"
+ "click .button.return": "onReturnClicked"
+ "click .button.save": "onSaveClicked"
+ "click .question a": "onQuestionClicked"
+ "input textarea": "onTextChanged"
# Private Methods ##############################################################################
@@ -219,22 +220,22 @@ module.exports = class MarkdownSectionController extends BaseController
result = match
item = @_modPack.findItemByName name
if item?
- display = @_modPack.findItemDisplay item.slug
- result = "[#{name}](#{display.itemUrl})"
+ display = new ItemDisplay item
+ result = "[#{name}](#{display.url})"
return result
_updateButtonStates: ->
for $button in [ @$previewButton, @$saveButton ]
if @_imageListController.valid
- $button.prop 'disabled', false
+ $button.prop "disabled", false
else
- $button.prop 'disabled', true
+ $button.prop "disabled", true
_updateSizer: ->
text = @model
if @model?
- text = text.replace /\n/g, '
'
+ text = text.replace /\n/g, "
"
@$sizer.html text
@@ -254,22 +255,22 @@ module.exports = class MarkdownSectionController extends BaseController
logger.verbose => "Updating markdown section visibility for state: #{@state}"
elements =
- appologizingPanel: @$('.appologizing')
- cancelButton: @$('.button.cancel')
- confirmingPanel: @$('.confirming')
- creatingPanel: @$('.creating')
- editButton: @$('.button.edit')
- editorPanel: @$('.editor')
- footerPanel: @$('.footer')
- imageList: @$('.view__markdown_image_list')
+ appologizingPanel: @$(".appologizing")
+ cancelButton: @$(".button.cancel")
+ confirmingPanel: @$(".confirming")
+ creatingPanel: @$(".creating")
+ editButton: @$(".button.edit")
+ editorPanel: @$(".editor")
+ footerPanel: @$(".footer")
+ imageList: @$(".view__markdown_image_list")
markdownPanel: @$markdownPanel
previewButton: @$previewButton
- returnButton: @$('.button.return')
+ returnButton: @$(".button.return")
saveButton: @$saveButton
- waitingPanel: @$('.waiting')
+ waitingPanel: @$(".waiting")
visible = {}
- errorText = ''
+ errorText = ""
if @state is @State.appologizing
visible = appologizingPanel:true
diff --git a/src/client/site/common/mod_version_selector/mod_version_selector.jade b/src/client/site/common/mod_version_selector/mod_version_selector.jade
index af77d0254..158b81d48 100644
--- a/src/client/site/common/mod_version_selector/mod_version_selector.jade
+++ b/src/client/site/common/mod_version_selector/mod_version_selector.jade
@@ -2,8 +2,5 @@
.toggle
span.checkbox
span.label I have this mod in my modpack
- .version
- span Version:
- select
.warning.
PLEASE NOTE: Crafting plans, search, and other features will ignore items and recipes from this mod.
diff --git a/src/client/site/common/mod_version_selector/mod_version_selector_controller.coffee b/src/client/site/common/mod_version_selector/mod_version_selector_controller.coffee
index 125a8debd..b50805a05 100644
--- a/src/client/site/common/mod_version_selector/mod_version_selector_controller.coffee
+++ b/src/client/site/common/mod_version_selector/mod_version_selector_controller.coffee
@@ -5,97 +5,59 @@
# All rights reserved.
#
-BaseController = require '../../base_controller'
-{Mod} = require('crafting-guide-common').deprecated.game
+BaseController = require "../../base_controller"
+{Mod} = require("crafting-guide-common").models
########################################################################################################################
module.exports = class ModVersionSelectorController extends BaseController
constructor: (options={})->
- if not options.model? then throw new Error 'options.model is required'
- options.templateName = 'common/mod_version_selector'
+ if options.model?.constructor isnt Mod then throw new Error "options.model must be a Mod"
+ options.templateName = "common/mod_version_selector"
super options
# Event Methods ################################################################################
onToggleEnabled: ->
- if @model.activeVersion is Mod.Version.None
- tracker.trackEvent c.tracking.category.modPack, 'toggle-on', @model.slug
- @model.activeVersion = Mod.Version.Latest
+ if not @model.isEnabled
+ tracker.trackEvent c.tracking.category.modPack, "toggle-on", @model.id
+ @model.isEnabled = true
else
- tracker.trackEvent c.tracking.category.modPack, 'toggle-off', @model.slug
- @model.activeVersion = Mod.Version.None
+ tracker.trackEvent c.tracking.category.modPack, "toggle-off", @model.id
+ @model.isEnabled = false
return false
- onVersionChanged: ->
- @model.activeVersion = @$versionSelector.val()
- tracker.trackEvent c.tracking.category.modPack, 'select-version', "#{@model.slug}@#{@model.activeVersion}"
- return false
-
- # Property Methods #############################################################################
-
- Object.defineProperties @prototype,
-
- effectiveModVersion:
- get: ->
- modVersion = @model.activeModVersion
- modVersion ?= @model.getModVersion Mod.Version.Latest
- modVersion.fetch() if modVersion?
- return modVersion
-
# BaseController Overrides #####################################################################
onDidRender: ->
- @$toggleSection = @$('.toggle')
- @$versionSection = @$('.version')
- @$versionSelector = @$('.version select')
- @$warning = @$('.warning')
+ @$toggleSection = @$(".toggle")
+ @$warning = @$(".warning")
super
refresh: ->
+ console.log "refreshing"
@_refreshEnabled()
- @_refreshVersionSelector()
super
# Backbone.View Overrides ######################################################################
events: ->
return _.extend super,
- 'change .version select': 'onVersionChanged'
- 'click .toggle': 'onToggleEnabled'
+ "click .toggle": "onToggleEnabled"
# Private Methods ##############################################################################
_refreshEnabled: ->
- if @model.slug in c.requiredMods
+ if @model.id in c.requiredMods
@hide @$toggleSection
else
@show @$toggleSection
- if @model.activeVersion is Mod.Version.None
- @$toggleSection.removeClass 'enabled'
+ if not @model.isEnabled
+ @$toggleSection.removeClass "enabled"
@show @$warning
else
- @$toggleSection.addClass 'enabled'
+ @$toggleSection.addClass "enabled"
@hide @$warning
-
- _refreshVersionSelector: ->
- modVersions = @model.modVersions
-
- if (@model.activeVersion is Mod.Version.None) or modVersions.length < 2
- @hide @$versionSection
- else
- @show @$versionSection
-
- selectedModVersion = @effectiveModVersion
-
- @$versionSelector.empty()
-
- for modVersion in @model.modVersions
- $option = $("")
- if modVersion is selectedModVersion
- $option.attr 'selected', 'true'
- @$versionSelector.append $option
- @$versionSelector.css display:''
diff --git a/src/client/site/common/recipe/crafting_table/crafting_table.jade b/src/client/site/common/recipe/crafting_table/crafting_table.jade
new file mode 100644
index 000000000..16d805b81
--- /dev/null
+++ b/src/client/site/common/recipe/crafting_table/crafting_table.jade
@@ -0,0 +1,19 @@
+//-
+//- Crafting Guide - crafting_table.jade
+//-
+//- Copyright (c) 2015-2017 by Redwood Labs
+//- All rights reserved.
+//-
+
+.view__crafting_table
+ .input_inventory
+ .view__inventory
+ .grid_block
+ .input_grid
+ .view__crafting_grid
+ .tool
+ .output_slot
+ .view__slot
+ .multiplier
+ .output_inventory
+ .view__inventory
diff --git a/src/client/site/common/recipe/crafting_table/crafting_table.scss b/src/client/site/common/recipe/crafting_table/crafting_table.scss
new file mode 100644
index 000000000..3f8d5d173
--- /dev/null
+++ b/src/client/site/common/recipe/crafting_table/crafting_table.scss
@@ -0,0 +1,103 @@
+//
+// Crafting Guide - crafting_table.scss
+//
+// Copyright © 2014-2017 by Redwood Labs
+// All rights reserved.
+//
+
+.view__crafting_table {
+ display: flex;
+
+ .input_inventory {
+ flex: 1 1 100%;
+
+ display: flex;
+ margin-right: $size-margin-large;
+ }
+
+ .grid_block {
+ flex: 1 1 100%;
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .input_grid {
+ flex: 0 0 auto;
+
+ align-items : center;
+ display : flex;
+ flex-direction : column;
+
+ .view__crafting_grid {
+ flex: 0 0 auto;
+ }
+
+ .tool {
+ margin-top : $size-margin-small;
+
+ font-family : $font-family-text;
+ font-size : $font-size-medium;
+ }
+ }
+
+ .output_slot {
+ flex: 0 0 auto;
+ margin-left: $size-margin-large;
+
+ display : flex;
+ flex-direction : column;
+ justify-content : center;
+ align-items : center;
+
+ .view__slot {
+ border: $size-border-medium solid $color-gray-medium;
+ }
+
+ .multiplier {
+ font-family : $font-family-header;
+ font-size : $font-size-large;
+ margin-top : $size-margin-medium;
+ }
+ }
+ }
+
+ .output_inventory {
+ flex: 1 1 100%;
+ display: flex;
+ margin-left: $size-margin-large;
+ }
+}
+
+@include screen-size(mobile) {
+ .view__crafting_table {
+ border-bottom: 1px solid $color-gray-light;
+ padding-bottom: $size-margin-medium;
+
+ flex-direction: column;
+ align-items: center;
+
+ .input_inventory {
+ flex: 0 0 auto;
+ margin-bottom: $size-margin-small;
+ }
+
+ .grid_block {
+ flex: 0 0 auto;
+
+ .tool {
+ margin-bottom: $size-margin-medium;
+ }
+ }
+
+ .output_inventory {
+ flex: 0 0 auto;
+ margin-left: 0;
+ }
+
+ .view__inventory {
+ margin-left: $size-margin-medium;
+ margin-right: $size-margin-medium;
+ }
+ }
+}
diff --git a/src/client/site/common/recipe/crafting_table/crafting_table_controller.coffee b/src/client/site/common/recipe/crafting_table/crafting_table_controller.coffee
new file mode 100644
index 000000000..dc1d59b3a
--- /dev/null
+++ b/src/client/site/common/recipe/crafting_table/crafting_table_controller.coffee
@@ -0,0 +1,95 @@
+#
+# Crafting Guide - crafting_table_controller.coffee
+#
+# Copyright © 2014-2017 by Redwood Labs
+# All rights reserved.
+#
+
+BaseController = require "../../../base_controller"
+CraftingGridController = require "../../crafting_grid/crafting_grid_controller"
+InventoryController = require "../../inventory/inventory_controller"
+ItemDisplay = require "../../../../models/site/item_display"
+RecipeDisplay = require "../../../../models/site/recipe_display"
+SlotController = require "../../slot/slot_controller"
+{StringBuilder} = require("crafting-guide-common").util
+
+########################################################################################################################
+
+module.exports = class CraftingTableController extends BaseController
+
+ constructor: (options={})->
+ if not options.imageLoader? then throw new Error "options.imageLoader is required"
+ if not options.modPack? then throw new Error "options.modPack is required"
+ if not options.router? then throw new Error "options.router is required"
+ options.templateName = "common/recipe/crafting_table"
+ super options
+
+ @_imageLoader = options.imageLoader
+ @_modPack = options.modPack
+ @_router = options.router
+
+ # BaseController Overrides #####################################################################
+
+ onDidRender: ->
+ options = editable:false, modPack:@_modPack, imageLoader:@_imageLoader, router:@_router
+
+ @_inputController = @addChild InventoryController, ".input_inventory .view__inventory", options
+ @_gridController = @addChild CraftingGridController, ".input_grid .view__crafting_grid", options
+ @_outputSlotController = @addChild SlotController, ".output_slot .view__slot", options
+ @_outputController = @addChild InventoryController, ".output_inventory .view__inventory", options
+
+ @$inputInventorySection = @$(".input_inventory")
+ @$multiplier = @$(".multiplier")
+ @$outputImg = @$(".output.slot img")
+ @$outputInventorySection = @$(".output_inventory")
+ @$outputLink = @$(".output.slot a")
+ @$outputQuantity = @$(".quantity")
+ @$outputSlotSection = @$(".output_slot")
+ @$toolContainer = @$(".tool")
+ super
+
+ onWillChangeModel: (oldModel, newModel)->
+ if not newModel? then throw new Error "model is required"
+ if newModel.constructor isnt RecipeDisplay then throw new Error "model must be a RecipeDisplay"
+ return super oldModel, newModel
+
+ refresh: ->
+ @_inputController.model = @model?.getInventory()
+ @_gridController.model = @model?.recipe
+ @_outputSlotController.model = @model?.recipe.output
+ @_outputController.model = @model?.getOutputInventory()
+
+ @_refreshMultiplier()
+ @_refreshSections()
+ @_refreshTools()
+ super
+
+ # Backbone.View Methods ########################################################################
+
+ events: ->
+ return _.extend super,
+ "click a": "routeLinkClick"
+
+ # Private Methods ##############################################################################
+
+ _refreshMultiplier: ->
+ if @model.multiplier > 1
+ @$multiplier.html "x#{@model.multiplier}"
+ else
+ @$multiplier.html ""
+
+ _refreshSections: ->
+ @$inputInventorySection.css display:(if @model.showInputInventory then "" else "none")
+ @$outputInventorySection.css display:(if @model.showOutputInventory then "" else "none")
+ @$outputSlotSection.css display:(if @model.showOutputSlot then "" else "none")
+
+ _refreshTools: ->
+ @$toolContainer.empty()
+ return unless @model?
+
+ toolLinks = []
+ for itemId, item of @model.tools
+ display = new ItemDisplay item
+ toolLinks.push "#{display.name}"
+
+ @$toolContainer.html toolLinks.join ", "
diff --git a/src/client/site/item_page/multiblock_viewer/multiblock/multiblock.jade b/src/client/site/common/recipe/multiblock_viewer/multiblock/multiblock.jade
similarity index 100%
rename from src/client/site/item_page/multiblock_viewer/multiblock/multiblock.jade
rename to src/client/site/common/recipe/multiblock_viewer/multiblock/multiblock.jade
diff --git a/src/client/site/item_page/multiblock_viewer/multiblock/multiblock.scss b/src/client/site/common/recipe/multiblock_viewer/multiblock/multiblock.scss
similarity index 100%
rename from src/client/site/item_page/multiblock_viewer/multiblock/multiblock.scss
rename to src/client/site/common/recipe/multiblock_viewer/multiblock/multiblock.scss
diff --git a/src/client/site/item_page/multiblock_viewer/multiblock/multiblock_controller.coffee b/src/client/site/common/recipe/multiblock_viewer/multiblock/multiblock_controller.coffee
similarity index 79%
rename from src/client/site/item_page/multiblock_viewer/multiblock/multiblock_controller.coffee
rename to src/client/site/common/recipe/multiblock_viewer/multiblock/multiblock_controller.coffee
index 914e230fb..678cec969 100644
--- a/src/client/site/item_page/multiblock_viewer/multiblock/multiblock_controller.coffee
+++ b/src/client/site/common/recipe/multiblock_viewer/multiblock/multiblock_controller.coffee
@@ -1,11 +1,12 @@
-###
-Crafting Guide - multiblock_controller.coffee
+#
+# Crafting Guide - multiblock_controller.coffee
+#
+# Copyright (c) 2014-2017 by Redwood Labs
+# All rights reserved.
+#
-Copyright (c) 2014-2015 by Redwood Labs
-All rights reserved.
-###
-
-BaseController = require '../../../base_controller'
+BaseController = require "../../../../base_controller"
+ItemDisplay = require "../../../../../models/site/item_display"
########################################################################################################################
@@ -25,9 +26,9 @@ module.exports = class MultiblockController extends BaseController
@::MAX_DROP_DELAY = 250 # ms
constructor: (options={})->
- if not options.imageLoader? then throw new Error 'options.imageLoader is required'
- if not options.modPack? then throw new Error 'options.modPack is required'
- options.templateName = 'item_page/multiblock_viewer/multiblock'
+ if not options.imageLoader? then throw new Error "options.imageLoader is required"
+ if not options.modPack? then throw new Error "options.modPack is required"
+ options.templateName = "common/recipe/multiblock_viewer/multiblock"
super options
@_currentLayer = 0
@@ -63,11 +64,11 @@ module.exports = class MultiblockController extends BaseController
# BaseController Overrides #####################################################################
onDidRender: ->
- @$outline = @$('.outline')
+ @$outline = @$(".outline")
super
refresh: ->
- @$el.css 'height':@_computeMinHeight(), 'width':@_computeMinWidth()
+ @$el.css "height":@_computeMinHeight(), "width":@_computeMinWidth()
@_refreshBlockCache()
@_refreshAllBlocks()
@@ -76,7 +77,7 @@ module.exports = class MultiblockController extends BaseController
# Private Methods ##############################################################################
_computePosition: (x, y, z, options={})->
- if not @model? then return left:0, top:-@IMAGE_SIZE, 'z-index':0, opacity:0.0
+ if not @model? then return left:0, top:-@IMAGE_SIZE, "z-index":0, opacity:0.0
options.hideUpperLayers ?= false
pxWidth = @$el.width()
@@ -93,7 +94,7 @@ module.exports = class MultiblockController extends BaseController
zindex = ((@model.width - x) + (@model.depth - z) + ((@model.width * @model.depth) * y)) * 2
- return left:left, top:top, 'z-index':zindex, opacity:opacity
+ return left:left, top:top, "z-index":zindex, opacity:opacity
_computeMinHeight: ->
return 0 unless @model?
@@ -130,23 +131,23 @@ module.exports = class MultiblockController extends BaseController
for z in [0...@model.depth]
@_blockCache[x][y][z] ?= null
- for el in @$('.block')
+ for el in @$(".block")
$el = $(el)
- @_blockCache[$el.data('x')][$el.data('y')][$el.data('z')] = $el
+ @_blockCache[$el.data("x")][$el.data("y")][$el.data("z")] = $el
_refreshBlock: (x, y, z)->
return unless @model?
- stack = @model.getStackAt x, y, z
+ stack = @model.getInputAt x, y, z
$block = @_blockCache[x][y][z]
position = @_computePosition x, y, z, hideUpperLayers:true
move = false
if stack?
- itemDisplay = @_modPack.findItemDisplay stack.itemSlug
+ itemDisplay = new ItemDisplay stack.item
if not $block?
- $block = $("")
+ $block = $("
")
$block.css position, top:-@IMAGE_SIZE, opacity:0.0
@_registerHoverHandlers $block, y, itemDisplay
@_imageLoader.load itemDisplay.iconUrl, $block
@@ -154,10 +155,10 @@ module.exports = class MultiblockController extends BaseController
@$el.append $block
move = true
else
- $block.attr 'src', itemDisplay.iconUrl
+ $block.attr "src", itemDisplay.iconUrl
move = true
else if $block?
- $block.attr 'src', ''
+ $block.attr "src", ""
move = true
if move then _.delay (-> $block.css position), @_randomDropDelay()
@@ -174,10 +175,10 @@ module.exports = class MultiblockController extends BaseController
_registerHoverHandlers: ($el, y, itemDisplay)->
startHovering = =>
return unless y is @_currentLayer
- zIndex = parseInt($el.css('z-index')) + 1
+ zIndex = parseInt($el.css("z-index")) + 1
zIndex = if _.isNaN(zIndex) then 0 else zIndex
- @$outline.css opacity:1.0, top:$el.css('top'), left:$el.css('left'), 'z-index':zIndex
+ @$outline.css opacity:1.0, top:$el.css("top"), left:$el.css("left"), "z-index":zIndex
@_onHovering itemDisplay
if @_hoverTimer? then clearTimeout @_hoverTimer
diff --git a/src/client/site/item_page/multiblock_viewer/multiblock_viewer.jade b/src/client/site/common/recipe/multiblock_viewer/multiblock_viewer.jade
similarity index 100%
rename from src/client/site/item_page/multiblock_viewer/multiblock_viewer.jade
rename to src/client/site/common/recipe/multiblock_viewer/multiblock_viewer.jade
diff --git a/src/client/site/item_page/multiblock_viewer/multiblock_viewer.scss b/src/client/site/common/recipe/multiblock_viewer/multiblock_viewer.scss
similarity index 100%
rename from src/client/site/item_page/multiblock_viewer/multiblock_viewer.scss
rename to src/client/site/common/recipe/multiblock_viewer/multiblock_viewer.scss
diff --git a/src/client/site/common/recipe/multiblock_viewer/multiblock_viewer_controller.coffee b/src/client/site/common/recipe/multiblock_viewer/multiblock_viewer_controller.coffee
new file mode 100644
index 000000000..2a6e40c5f
--- /dev/null
+++ b/src/client/site/common/recipe/multiblock_viewer/multiblock_viewer_controller.coffee
@@ -0,0 +1,96 @@
+#
+# Crafting Guide - multiblock_viewer_controller.coffee
+#
+# Copyright © 2014-2017 by Redwood Labs
+# All rights reserved.
+#
+
+BaseController = require "../../../base_controller"
+InventoryController = require "../../inventory/inventory_controller"
+MultiblockController = require "./multiblock/multiblock_controller"
+RecipeDisplay = require "../../../../models/site/recipe_display"
+
+########################################################################################################################
+
+module.exports = class MultiblockViewerController extends BaseController
+
+ constructor: (options={})->
+ if not options.imageLoader? then throw new Error "options.imageLoader is required"
+ if not options.modPack? then throw new Error "options.modPack is required"
+ if not options.router? then throw new Error "options.router is required"
+ options.templateName = "common/recipe/multiblock_viewer"
+ super options
+
+ @_imageLoader = options.imageLoader
+ @_modPack = options.modPack
+ @_hoverTimer = null
+ @_router = options.router
+
+ # Event Methods ################################################################################
+
+ onBackClicked: ->
+ return if @$backButton.hasClass "disabled"
+ tracker.trackEvent c.tracking.category.multiblock, "back"
+ @multiblockController.goBackLayer()
+ @refresh()
+
+ onNextClicked: ->
+ return if @$nextButton.hasClass "disabled"
+ tracker.trackEvent c.tracking.category.multiblock, "next"
+ @multiblockController.goNextLayer()
+ @refresh()
+
+ onBlockHovered: (itemDisplay)->
+ if itemDisplay?
+ @$captionText.html itemDisplay.name
+ @_imageLoader.load itemDisplay.iconUrl, @$captionIcon
+ else
+ @$captionText.html " "
+ @$captionIcon.attr "src", "/images/empty.png"
+
+ # BaseController Overrides #####################################################################
+
+ onDidRender: ->
+ baseOptions = imageLoader:@_imageLoader, modPack:@_modPack, router:@_router
+
+ options = _.extend {editable:false}, baseOptions
+ @completeInventoryController = @addChild InventoryController, ".view__inventory.complete", options
+ @layerInventoryController = @addChild InventoryController, ".view__inventory.layer", options
+
+ options = _.extend {onHovering:(itemDisplay)=> @onBlockHovered(itemDisplay)}, baseOptions
+ @multiblockController = @addChild MultiblockController, ".view__multiblock", options
+
+ @$backButton = @$(".button.back")
+ @$nextButton = @$(".button.next")
+ @$captionText = @$(".caption p")
+ @$captionIcon = @$(".caption img")
+ super
+
+ onWillChangeModel: (oldModel, newModel)->
+ if not newModel? then throw new Error "model is required"
+ if newModel.constructor isnt RecipeDisplay then throw new Error "model must be a RecipeDisplay"
+ return super oldModel, newModel
+
+ refresh: ->
+ @completeInventoryController.model = @model.getInventory()
+ @layerInventoryController.model = @model.getInventory @multiblockController.currentLayer
+ @multiblockController.model = @model
+
+ if @multiblockController.hasBackLayer()
+ @$backButton.removeClass "disabled"
+ else
+ @$backButton.addClass "disabled"
+
+ if @multiblockController.hasNextLayer()
+ @$nextButton.removeClass "disabled"
+ else
+ @$nextButton.addClass "disabled"
+
+ super
+
+ # Backbone.View Overrides ######################################################################
+
+ events: ->
+ _.extend super,
+ "click .button.back": "onBackClicked"
+ "click .button.next": "onNextClicked"
diff --git a/src/client/site/common/recipe/recipe.jade b/src/client/site/common/recipe/recipe.jade
index 0acf46b76..95ae08bb5 100644
--- a/src/client/site/common/recipe/recipe.jade
+++ b/src/client/site/common/recipe/recipe.jade
@@ -1,14 +1,8 @@
//-
//- Crafting Guide - recipe.jade
//-
-//- Copyright (c) 2015 by Redwood Labs
+//- Copyright (c) 2014-2017 by Redwood Labs
//- All rights reserved.
//-
.view__recipe
- .input
- .view__crafting_grid
- .tool
- .output
- .view__slot
- .multiplier
\ No newline at end of file
diff --git a/src/client/site/common/recipe/recipe.scss b/src/client/site/common/recipe/recipe.scss
index 5d9bf6d57..1c9244d26 100644
--- a/src/client/site/common/recipe/recipe.scss
+++ b/src/client/site/common/recipe/recipe.scss
@@ -46,4 +46,4 @@
margin-top : $size-margin-medium;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/client/site/common/recipe/recipe_controller.coffee b/src/client/site/common/recipe/recipe_controller.coffee
index 9089af172..f625427eb 100644
--- a/src/client/site/common/recipe/recipe_controller.coffee
+++ b/src/client/site/common/recipe/recipe_controller.coffee
@@ -5,93 +5,57 @@
# All rights reserved.
#
-BaseController = require '../../base_controller'
-CraftingGridController = require '../crafting_grid/crafting_grid_controller'
-SlotController = require '../slot/slot_controller'
-{StringBuilder} = require('crafting-guide-common').util
+BaseController = require "../../base_controller"
+CraftingTableController = require "./crafting_table/crafting_table_controller"
+MultiblockViewerController = require "./multiblock_viewer/multiblock_viewer_controller"
+RecipeDisplay = require "../../../models/site/recipe_display"
########################################################################################################################
module.exports = class RecipeController extends BaseController
constructor: (options={})->
- if not options.imageLoader? then throw new Error 'options.imageLoader is required'
- if not options.modPack? then throw new Error 'options.modPack is required'
- if not options.router? then throw new Error 'options.router is required'
- options.templateName = 'common/recipe'
+ if not options.imageLoader? then throw new Error "options.imageLoader is required"
+ if not options.modPack? then throw new Error "options.modPack is required"
+ if not options.router? then throw new Error "options.router is required"
+ options.templateName = "common/recipe"
super options
@_imageLoader = options.imageLoader
@_modPack = options.modPack
- @_multiplier = options.multiplier
@_router = options.router
# BaseController Overrides #####################################################################
- onDidRender: ->
- @_gridController = @addChild CraftingGridController, '.view__crafting_grid',
- modPack: @_modPack
- imageLoader: @_imageLoader
- router: @_router
-
- @_outputSlotController = @addChild SlotController, '.output .view__slot',
- imageLoader: @_imageLoader
- modPack: @_modPack
- router: @_router
-
- @$multiplier = @$('.multiplier')
- @$outputImg = @$('.output img')
- @$outputLink = @$('.output a')
- @$outputQuantity = @$('.quantity')
- @$toolContainer = @$('.tool')
- super
+ onWillChangeModel: (oldModel, newModel)->
+ if not newModel? then throw new Error "model is required"
+ if newModel.constructor isnt RecipeDisplay then throw new Error "model must be a RecipeDisplay"
+ if @_typeController? then @_typeController.model = newModel
+ return super oldModel, newModel
refresh: ->
- @_gridController.model = @model
- @_outputSlotController.model = @model?.output?[0]
-
- @_refreshMultiplier()
- @_refreshTools()
+ return unless @model?
+ @_refreshRecipeType()
super
- # Property Methods #############################################################################
-
- Object.defineProperties @prototype,
- multiplier:
- get: ->
- @_multiplier ?= 1
- return @_multiplier
-
- set: (newMultiplier)->
- oldMultiplier = @_multiplier
- return if newMultiplier is oldMultiplier
-
- @_multiplier = newMultiplier
- @_refreshMultiplier()
-
- @trigger Event.change + ':multiplier', this, oldMultiplier, newMultiplier
- @trigger Event.change, this
-
- # Backbone.View Methods ########################################################################
-
- events: ->
- return _.extend super,
- 'click a': 'routeLinkClick'
-
# Private Methods ##############################################################################
- _refreshMultiplier: ->
- if @multiplier > 1
- @$multiplier.html "x#{@multiplier}"
- else
- @$multiplier.html ''
+ _lookupControllerFor: (recipeType)->
+ if recipeType is RecipeDisplay::RECIPE_TYPE.CRAFTING_TABLE then return CraftingTableController
+ if recipeType is RecipeDisplay::RECIPE_TYPE.MULTIBLOCK then return MultiblockViewerController
- _refreshTools: ->
- @$toolContainer.empty()
- return unless @model?
+ _refreshRecipeType: ->
+ return if @_renderedRecipeType is @model.type
+ @_renderedRecipeType = @model.type
- builder = new StringBuilder
- builder.loop @model.tools, delimiter:', ', onEach:(b, stack)=>
- display = @_modPack.findItemDisplay stack.itemSlug
- b.push "#{display.itemName}"
- @$toolContainer.html builder.toString()
+ if @_typeController?
+ @_typeController.remove()
+ @_typeController = null
+
+ return unless @_renderedRecipeType?
+
+ TypeController = @_lookupControllerFor @model.type
+
+ @$el.append "