From 42c7f00a324609e5236c0c134ad99968e7fcd533 Mon Sep 17 00:00:00 2001 From: Ganlv Date: Mon, 28 Jan 2019 04:51:21 +0800 Subject: [PATCH] Bundle svg files --- {public => assets}/images/bottom_left/1.svg | 0 {public => assets}/images/bottom_left/2.svg | 0 {public => assets}/images/bottom_left/3.svg | 0 {public => assets}/images/bottom_left/4.svg | 0 {public => assets}/images/bottom_left/5.svg | 0 {public => assets}/images/left/1.svg | 0 {public => assets}/images/left/2.svg | 0 {public => assets}/images/left/3.svg | 0 {public => assets}/images/left/4.svg | 0 {public => assets}/images/left/5.svg | 0 {public => assets}/images/top_left/1.svg | 0 {public => assets}/images/top_left/2.svg | 0 {public => assets}/images/top_left/3.svg | 0 {public => assets}/images/top_left/4.svg | 0 {public => assets}/images/top_left/5.svg | 0 package-lock.json | 257 +++++++++- package.json | 3 +- src/custom.d.ts | 4 + src/data.ts | 33 ++ src/lib/FakeXHRLoader.ts | 43 ++ src/lib/RawFile.ts | 21 + src/lib/RawSVGFile.ts | 18 + src/lib/fake-xml-http-request.d.ts | 17 + src/lib/fake-xml-http-request.js | 510 ++++++++++++++++++++ src/phaser.d.ts | 9 +- src/scenes/mainScene.ts | 3 +- webpack.config.js | 43 +- 27 files changed, 927 insertions(+), 34 deletions(-) rename {public => assets}/images/bottom_left/1.svg (100%) rename {public => assets}/images/bottom_left/2.svg (100%) rename {public => assets}/images/bottom_left/3.svg (100%) rename {public => assets}/images/bottom_left/4.svg (100%) rename {public => assets}/images/bottom_left/5.svg (100%) rename {public => assets}/images/left/1.svg (100%) rename {public => assets}/images/left/2.svg (100%) rename {public => assets}/images/left/3.svg (100%) rename {public => assets}/images/left/4.svg (100%) rename {public => assets}/images/left/5.svg (100%) rename {public => assets}/images/top_left/1.svg (100%) rename {public => assets}/images/top_left/2.svg (100%) rename {public => assets}/images/top_left/3.svg (100%) rename {public => assets}/images/top_left/4.svg (100%) rename {public => assets}/images/top_left/5.svg (100%) create mode 100644 src/custom.d.ts create mode 100644 src/lib/FakeXHRLoader.ts create mode 100644 src/lib/RawFile.ts create mode 100644 src/lib/RawSVGFile.ts create mode 100644 src/lib/fake-xml-http-request.d.ts create mode 100644 src/lib/fake-xml-http-request.js diff --git a/public/images/bottom_left/1.svg b/assets/images/bottom_left/1.svg similarity index 100% rename from public/images/bottom_left/1.svg rename to assets/images/bottom_left/1.svg diff --git a/public/images/bottom_left/2.svg b/assets/images/bottom_left/2.svg similarity index 100% rename from public/images/bottom_left/2.svg rename to assets/images/bottom_left/2.svg diff --git a/public/images/bottom_left/3.svg b/assets/images/bottom_left/3.svg similarity index 100% rename from public/images/bottom_left/3.svg rename to assets/images/bottom_left/3.svg diff --git a/public/images/bottom_left/4.svg b/assets/images/bottom_left/4.svg similarity index 100% rename from public/images/bottom_left/4.svg rename to assets/images/bottom_left/4.svg diff --git a/public/images/bottom_left/5.svg b/assets/images/bottom_left/5.svg similarity index 100% rename from public/images/bottom_left/5.svg rename to assets/images/bottom_left/5.svg diff --git a/public/images/left/1.svg b/assets/images/left/1.svg similarity index 100% rename from public/images/left/1.svg rename to assets/images/left/1.svg diff --git a/public/images/left/2.svg b/assets/images/left/2.svg similarity index 100% rename from public/images/left/2.svg rename to assets/images/left/2.svg diff --git a/public/images/left/3.svg b/assets/images/left/3.svg similarity index 100% rename from public/images/left/3.svg rename to assets/images/left/3.svg diff --git a/public/images/left/4.svg b/assets/images/left/4.svg similarity index 100% rename from public/images/left/4.svg rename to assets/images/left/4.svg diff --git a/public/images/left/5.svg b/assets/images/left/5.svg similarity index 100% rename from public/images/left/5.svg rename to assets/images/left/5.svg diff --git a/public/images/top_left/1.svg b/assets/images/top_left/1.svg similarity index 100% rename from public/images/top_left/1.svg rename to assets/images/top_left/1.svg diff --git a/public/images/top_left/2.svg b/assets/images/top_left/2.svg similarity index 100% rename from public/images/top_left/2.svg rename to assets/images/top_left/2.svg diff --git a/public/images/top_left/3.svg b/assets/images/top_left/3.svg similarity index 100% rename from public/images/top_left/3.svg rename to assets/images/top_left/3.svg diff --git a/public/images/top_left/4.svg b/assets/images/top_left/4.svg similarity index 100% rename from public/images/top_left/4.svg rename to assets/images/top_left/4.svg diff --git a/public/images/top_left/5.svg b/assets/images/top_left/5.svg similarity index 100% rename from public/images/top_left/5.svg rename to assets/images/top_left/5.svg diff --git a/package-lock.json b/package-lock.json index 2582715..2043fb5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -290,9 +290,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.2.0", - "resolved": "http://registry.npm.taobao.org/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.2.0.tgz", - "integrity": "sha1-iPX+w+etAZAUyX9+48mS8K2/f7g=", + "version": "7.3.1", + "resolved": "http://registry.npm.taobao.org/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.3.1.tgz", + "integrity": "sha1-9p+2oepqThxQOZSpHZz3bzxLNug=", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -528,6 +528,15 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.3.0", + "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-named-capturing-groups-regex/download/@babel/plugin-transform-named-capturing-groups-regex-7.3.0.tgz", + "integrity": "sha1-FAtSmFstbvDLCS7zspUCuZD5zVA=", + "dev": true, + "requires": { + "regexp-tree": "^0.1.0" + } + }, "@babel/plugin-transform-new-target": { "version": "7.0.0", "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-new-target/download/@babel/plugin-transform-new-target-7.0.0.tgz", @@ -626,19 +635,20 @@ } }, "@babel/preset-env": { - "version": "7.2.3", - "resolved": "http://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.2.3.tgz", - "integrity": "sha1-lIyN9NRgnJnH4BMBafBS6mp6iTM=", + "version": "7.3.1", + "resolved": "http://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.3.1.tgz", + "integrity": "sha1-OJ6MprF65nqvmiERZlAwvpI1Fds=", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.3.1", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", @@ -658,6 +668,7 @@ "@babel/plugin-transform-modules-commonjs": "^7.2.0", "@babel/plugin-transform-modules-systemjs": "^7.2.0", "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0", "@babel/plugin-transform-new-target": "^7.0.0", "@babel/plugin-transform-object-super": "^7.2.0", "@babel/plugin-transform-parameters": "^7.2.0", @@ -1373,13 +1384,13 @@ } }, "browserslist": { - "version": "4.3.7", - "resolved": "http://registry.npm.taobao.org/browserslist/download/browserslist-4.3.7.tgz", - "integrity": "sha1-8d5HmmRm6kegom3Mcl51BIF+Yko=", + "version": "4.4.1", + "resolved": "http://registry.npm.taobao.org/browserslist/download/browserslist-4.4.1.tgz", + "integrity": "sha1-QugolUtrKaelPjUid75ClHimkGI=", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000925", - "electron-to-chromium": "^1.3.96", + "caniuse-lite": "^1.0.30000929", + "electron-to-chromium": "^1.3.103", "node-releases": "^1.1.3" } }, @@ -1469,9 +1480,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30000927", - "resolved": "http://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30000927.tgz", - "integrity": "sha1-EUqd5P8eAfV5D+V47Nk0IcdSRmU=", + "version": "1.0.30000932", + "resolved": "http://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30000932.tgz", + "integrity": "sha1-0Bdj6c53gQliynOR/4J7WUnOQnI=", "dev": true }, "chalk": { @@ -1554,6 +1565,17 @@ } } }, + "cli-table3": { + "version": "0.5.1", + "resolved": "http://registry.npm.taobao.org/cli-table3/download/cli-table3-0.5.1.tgz", + "integrity": "sha1-AlI3LZTfxA29jfBgBfSPMfZW8gI=", + "dev": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, "cliui": { "version": "4.1.0", "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-4.1.0.tgz", @@ -1596,6 +1618,12 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "colors": { + "version": "1.3.3", + "resolved": "http://registry.npm.taobao.org/colors/download/colors-1.3.3.tgz", + "integrity": "sha1-OeAF1Uav4B4B+cTKj6UPaGoBIF0=", + "dev": true + }, "commander": { "version": "2.17.1", "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.17.1.tgz", @@ -2167,9 +2195,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.98", - "resolved": "http://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.98.tgz", - "integrity": "sha1-8gC9rISxEQ19mQTzT0/G1Vc6ipw=", + "version": "1.3.108", + "resolved": "http://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.108.tgz", + "integrity": "sha1-Lnmm/KpLPnx1q/hxUFvajiaMkQ4=", "dev": true }, "elliptic": { @@ -3945,9 +3973,9 @@ "dev": true }, "js-levenshtein": { - "version": "1.1.4", - "resolved": "http://registry.npm.taobao.org/js-levenshtein/download/js-levenshtein-1.1.4.tgz", - "integrity": "sha1-Olbjy/WJygCB6yLNm6CxKQoW0m4=", + "version": "1.1.6", + "resolved": "http://registry.npm.taobao.org/js-levenshtein/download/js-levenshtein-1.1.6.tgz", + "integrity": "sha1-xs7ljrNVA3LfjeuF+tXOZs4B1Z0=", "dev": true }, "js-tokens": { @@ -4996,6 +5024,29 @@ "unpipe": "1.0.0" } }, + "raw-loader": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/raw-loader/download/raw-loader-1.0.0.tgz", + "integrity": "sha1-P5iJ5z2tvamkJLznmAm0EzrUZAU=", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, "readable-stream": { "version": "2.3.6", "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.6.tgz", @@ -5056,6 +5107,170 @@ "safe-regex": "^1.1.0" } }, + "regexp-tree": { + "version": "0.1.0", + "resolved": "http://registry.npm.taobao.org/regexp-tree/download/regexp-tree-0.1.0.tgz", + "integrity": "sha1-pWrXdGCXiI6hZFdHkCnsk0W5arA=", + "dev": true, + "requires": { + "cli-table3": "^0.5.0", + "colors": "^1.1.2", + "yargs": "^10.0.3" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "http://registry.npm.taobao.org/cross-spawn/download/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "http://registry.npm.taobao.org/execa/download/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/get-stream/download/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/invert-kv/download/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/lcid/download/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/mem/download/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-2.1.0.tgz", + "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz", + "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "http://registry.npm.taobao.org/y18n/download/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "10.1.2", + "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-10.1.2.tgz", + "integrity": "sha1-RU0HTCsWpRpD4vt4B+T53mnMtcU=", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^8.1.0" + } + }, + "yargs-parser": { + "version": "8.1.0", + "resolved": "http://registry.npm.taobao.org/yargs-parser/download/yargs-parser-8.1.0.tgz", + "integrity": "sha1-8TdqM7Ziml0GN4KUTacyYx6WaVA=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, "regexpu-core": { "version": "4.4.0", "resolved": "http://registry.npm.taobao.org/regexpu-core/download/regexpu-core-4.4.0.tgz", diff --git a/package.json b/package.json index 1d19e10..5a591ed 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,11 @@ }, "devDependencies": { "@babel/core": "^7.2.2", - "@babel/preset-env": "^7.2.3", + "@babel/preset-env": "^7.3.1", "babel-loader": "^8.0.5", "copy-webpack-plugin": "^4.6.0", "expose-loader": "^0.7.5", + "raw-loader": "^1.0.0", "ts-loader": "^5.3.3", "typescript": "^3.2.4", "webpack": "^4.29.0", diff --git a/src/custom.d.ts b/src/custom.d.ts new file mode 100644 index 0000000..156473a --- /dev/null +++ b/src/custom.d.ts @@ -0,0 +1,4 @@ +declare module "*.svg" { + const content: any; + export default content; +} diff --git a/src/data.ts b/src/data.ts index cc90958..38a5676 100644 --- a/src/data.ts +++ b/src/data.ts @@ -1,4 +1,37 @@ +import * as bottom_left_1 from "../assets/images/bottom_left/1.svg"; +import * as bottom_left_2 from "../assets/images/bottom_left/2.svg"; +import * as bottom_left_3 from "../assets/images/bottom_left/3.svg"; +import * as bottom_left_4 from "../assets/images/bottom_left/4.svg"; +import * as bottom_left_5 from "../assets/images/bottom_left/5.svg"; +import * as left_1 from "../assets/images/left/1.svg"; +import * as left_2 from "../assets/images/left/2.svg"; +import * as left_3 from "../assets/images/left/3.svg"; +import * as left_4 from "../assets/images/left/4.svg"; +import * as left_5 from "../assets/images/left/5.svg"; +import * as top_left_1 from "../assets/images/top_left/1.svg"; +import * as top_left_2 from "../assets/images/top_left/2.svg"; +import * as top_left_3 from "../assets/images/top_left/3.svg"; +import * as top_left_4 from "../assets/images/top_left/4.svg"; +import * as top_left_5 from "../assets/images/top_left/5.svg"; + export default { + texturesData: { + "images/bottom_left/1.svg": bottom_left_1, + "images/bottom_left/2.svg": bottom_left_2, + "images/bottom_left/3.svg": bottom_left_3, + "images/bottom_left/4.svg": bottom_left_4, + "images/bottom_left/5.svg": bottom_left_5, + "images/left/1.svg": left_1, + "images/left/2.svg": left_2, + "images/left/3.svg": left_3, + "images/left/4.svg": left_4, + "images/left/5.svg": left_5, + "images/top_left/1.svg": top_left_1, + "images/top_left/2.svg": top_left_2, + "images/top_left/3.svg": top_left_3, + "images/top_left/4.svg": top_left_4, + "images/top_left/5.svg": top_left_5, + }, textures: [ "images/bottom_left/1.svg", "images/bottom_left/2.svg", diff --git a/src/lib/FakeXHRLoader.ts b/src/lib/FakeXHRLoader.ts new file mode 100644 index 0000000..996bc8b --- /dev/null +++ b/src/lib/FakeXHRLoader.ts @@ -0,0 +1,43 @@ +import FakeXMLHttpRequest from "./fake-xml-http-request"; +import RawFile from "./RawFile"; + +export default function FakeXHRLoader(file: RawFile, config: XHRSettingsObject): XMLHttpRequest { + /** + * @link https://github.com/pretenderjs/FakeXMLHttpRequest/blob/master/src/fake-xml-http-request.js + */ + var xhr = new FakeXMLHttpRequest(); + + xhr.open("GET", file.src, config.async, config.user, config.password); + + xhr.responseType = file.xhrSettings.responseType; + xhr.timeout = config.timeout; + + if (config.header && config.headerValue) { + xhr.setRequestHeader(config.header, config.headerValue); + } + + if (config.requestedWith) { + xhr.setRequestHeader("X-Requested-With", config.requestedWith); + } + + if (config.overrideMimeType) { + xhr.overrideMimeType(config.overrideMimeType); + } + + // After a successful request, the xhr.response property will contain the requested data as a DOMString, ArrayBuffer, Blob, or Document (depending on what was set for responseType.) + + xhr.onload = file.onLoad.bind(file, xhr); + xhr.onerror = file.onError.bind(file); + xhr.onprogress = file.onProgress.bind(file); + + // This is the only standard method, the ones above are browser additions (maybe not universal?) + // xhr.onreadystatechange + + xhr.send(); + + setTimeout(() => { + xhr.respond(200, {"Content-Type": "application/octet-stream"}, file.rawData); + }, 1); + + return xhr; +}; diff --git a/src/lib/RawFile.ts b/src/lib/RawFile.ts new file mode 100644 index 0000000..d8d9993 --- /dev/null +++ b/src/lib/RawFile.ts @@ -0,0 +1,21 @@ +import FakeXHRLoader from "./FakeXHRLoader"; + +export default class RawFile extends Phaser.Loader.File { + rawData: string; + + constructor(loader: Phaser.Loader.LoaderPlugin, type: string, key: string, data: string) { + super(loader, { + type: type, + key: key, + }); + this.rawData = data; + } + + load(): void { + if (this.state === Phaser.Loader.FILE_POPULATED) { + this.loader.nextFile(this, true); + } else { + this.xhrLoader = FakeXHRLoader(this, this.loader.xhr); + } + } +} diff --git a/src/lib/RawSVGFile.ts b/src/lib/RawSVGFile.ts new file mode 100644 index 0000000..6707ef5 --- /dev/null +++ b/src/lib/RawSVGFile.ts @@ -0,0 +1,18 @@ +import FakeXHRLoader from "./FakeXHRLoader"; + +export default class RawSVGFile extends Phaser.Loader.FileTypes.SVGFile { + rawData: string; + + constructor(loader: Phaser.Loader.LoaderPlugin, key: string | Phaser.Loader.FileTypes.SVGFileConfig, data: string, svgConfig?: Phaser.Loader.FileTypes.SVGSizeConfig) { + super(loader, key, undefined, svgConfig); + this.rawData = data; + } + + load(): void { + if (this.state === Phaser.Loader.FILE_POPULATED) { + this.loader.nextFile(this, true); + } else { + this.xhrLoader = FakeXHRLoader(this, this.loader.xhr); + } + } +} diff --git a/src/lib/fake-xml-http-request.d.ts b/src/lib/fake-xml-http-request.d.ts new file mode 100644 index 0000000..e4a0bb0 --- /dev/null +++ b/src/lib/fake-xml-http-request.d.ts @@ -0,0 +1,17 @@ +export default class FakeXMLHttpRequest extends XMLHttpRequest { + /* + Forces a response on to the FakeXMLHttpRequest object. + This is the public API for faking responses. This function + takes a number status, headers object, and string body: + ``` + xhr.respond(404, {Content-Type: 'text/plain'}, "Sorry. This object was not found.") + ``` + */ + respond( + statusCode: number, + headersObject?: { + [k: string]: string; + }, + bodyText?: string + ): void; +} diff --git a/src/lib/fake-xml-http-request.js b/src/lib/fake-xml-http-request.js new file mode 100644 index 0000000..93f73e1 --- /dev/null +++ b/src/lib/fake-xml-http-request.js @@ -0,0 +1,510 @@ +/** + * Minimal Event interface implementation + * + * Original implementation by Sven Fuchs: https://gist.github.com/995028 + * Modifications and tests by Christian Johansen. + * + * @author Sven Fuchs (svenfuchs@artweb-design.de) + * @author Christian Johansen (christian@cjohansen.no) + * @license BSD + * + * Copyright (c) 2011 Sven Fuchs, Christian Johansen + */ + +var _Event = function Event(type, bubbles, cancelable, target) { + this.type = type; + this.bubbles = bubbles; + this.cancelable = cancelable; + this.target = target; +}; + +_Event.prototype = { + stopPropagation: function () {}, + preventDefault: function () { + this.defaultPrevented = true; + } +}; + +/* + Used to set the statusText property of an xhr object +*/ +var httpStatusCodes = { + 100: "Continue", + 101: "Switching Protocols", + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non-Authoritative Information", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 300: "Multiple Choice", + 301: "Moved Permanently", + 302: "Found", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 307: "Temporary Redirect", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Timeout", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request-URI Too Long", + 415: "Unsupported Media Type", + 416: "Requested Range Not Satisfiable", + 417: "Expectation Failed", + 422: "Unprocessable Entity", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Timeout", + 505: "HTTP Version Not Supported" +}; + + +/* + Cross-browser XML parsing. Used to turn + XML responses into Document objects + Borrowed from JSpec +*/ +function parseXML(text) { + var xmlDoc; + + if (typeof DOMParser != "undefined") { + var parser = new DOMParser(); + xmlDoc = parser.parseFromString(text, "text/xml"); + } else { + xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async = "false"; + xmlDoc.loadXML(text); + } + + return xmlDoc; +} + +/* + Without mocking, the native XMLHttpRequest object will throw + an error when attempting to set these headers. We match this behavior. +*/ +var unsafeHeaders = { + "Accept-Charset": true, + "Accept-Encoding": true, + "Connection": true, + "Content-Length": true, + "Cookie": true, + "Cookie2": true, + "Content-Transfer-Encoding": true, + "Date": true, + "Expect": true, + "Host": true, + "Keep-Alive": true, + "Referer": true, + "TE": true, + "Trailer": true, + "Transfer-Encoding": true, + "Upgrade": true, + "User-Agent": true, + "Via": true +}; + +/* + Adds an "event" onto the fake xhr object + that just calls the same-named method. This is + in case a library adds callbacks for these events. +*/ +function _addEventListener(eventName, xhr){ + xhr.addEventListener(eventName, function (event) { + var listener = xhr["on" + eventName]; + + if (listener && typeof listener == "function") { + listener.call(event.target, event); + } + }); +} + +function EventedObject() { + this._eventListeners = {}; + var events = ["loadstart", "progress", "load", "abort", "loadend"]; + for (var i = events.length - 1; i >= 0; i--) { + _addEventListener(events[i], this); + } +}; + +EventedObject.prototype = { + /* + Duplicates the behavior of native XMLHttpRequest's addEventListener function + */ + addEventListener: function addEventListener(event, listener) { + this._eventListeners[event] = this._eventListeners[event] || []; + this._eventListeners[event].push(listener); + }, + + /* + Duplicates the behavior of native XMLHttpRequest's removeEventListener function + */ + removeEventListener: function removeEventListener(event, listener) { + var listeners = this._eventListeners[event] || []; + + for (var i = 0, l = listeners.length; i < l; ++i) { + if (listeners[i] == listener) { + return listeners.splice(i, 1); + } + } + }, + + /* + Duplicates the behavior of native XMLHttpRequest's dispatchEvent function + */ + dispatchEvent: function dispatchEvent(event) { + var type = event.type; + var listeners = this._eventListeners[type] || []; + + for (var i = 0; i < listeners.length; i++) { + if (typeof listeners[i] == "function") { + listeners[i].call(this, event); + } else { + listeners[i].handleEvent(event); + } + } + + return !!event.defaultPrevented; + }, + + /* + Triggers an `onprogress` event with the given parameters. + */ + _progress: function _progress(lengthComputable, loaded, total) { + var event = new _Event('progress'); + event.target = this; + event.lengthComputable = lengthComputable; + event.loaded = loaded; + event.total = total; + this.dispatchEvent(event); + } +} + +/* + Constructor for a fake window.XMLHttpRequest +*/ +function FakeXMLHttpRequest() { + EventedObject.call(this); + this.readyState = FakeXMLHttpRequest.UNSENT; + this.requestHeaders = {}; + this.requestBody = null; + this.status = 0; + this.statusText = ""; + this.upload = new EventedObject(); +} + +FakeXMLHttpRequest.prototype = new EventedObject(); + +// These status codes are available on the native XMLHttpRequest +// object, so we match that here in case a library is relying on them. +FakeXMLHttpRequest.UNSENT = 0; +FakeXMLHttpRequest.OPENED = 1; +FakeXMLHttpRequest.HEADERS_RECEIVED = 2; +FakeXMLHttpRequest.LOADING = 3; +FakeXMLHttpRequest.DONE = 4; + +var FakeXMLHttpRequestProto = { + UNSENT: 0, + OPENED: 1, + HEADERS_RECEIVED: 2, + LOADING: 3, + DONE: 4, + async: true, + withCredentials: false, + + /* + Duplicates the behavior of native XMLHttpRequest's open function + */ + open: function open(method, url, async, username, password) { + this.method = method; + this.url = url; + this.async = typeof async == "boolean" ? async : true; + this.username = username; + this.password = password; + this.responseText = null; + this.responseXML = null; + this.responseURL = url; + this.requestHeaders = {}; + this.sendFlag = false; + this._readyStateChange(FakeXMLHttpRequest.OPENED); + }, + + /* + Duplicates the behavior of native XMLHttpRequest's setRequestHeader function + */ + setRequestHeader: function setRequestHeader(header, value) { + verifyState(this); + + if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) { + throw new Error("Refused to set unsafe header \"" + header + "\""); + } + + if (this.requestHeaders[header]) { + this.requestHeaders[header] += "," + value; + } else { + this.requestHeaders[header] = value; + } + }, + + /* + Duplicates the behavior of native XMLHttpRequest's send function + */ + send: function send(data) { + verifyState(this); + + + if (!/^(get|head)$/i.test(this.method)) { + var hasContentTypeHeader = false + + Object.keys(this.requestHeaders).forEach(function (key) { + if (key.toLowerCase() === 'content-type') { + hasContentTypeHeader = true; + } + }); + + if (!hasContentTypeHeader && !(data || '').toString().match('FormData')) { + this.requestHeaders["Content-Type"] = "text/plain;charset=UTF-8"; + } + + this.requestBody = data; + } + + this.errorFlag = false; + this.sendFlag = this.async; + this._readyStateChange(FakeXMLHttpRequest.OPENED); + + if (typeof this.onSend == "function") { + this.onSend(this); + } + + this.dispatchEvent(new _Event("loadstart", false, false, this)); + }, + + /* + Duplicates the behavior of native XMLHttpRequest's abort function + */ + abort: function abort() { + this.aborted = true; + this.responseText = null; + this.errorFlag = true; + this.requestHeaders = {}; + + this.dispatchEvent(new _Event("abort", false, false, this)); + + if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) { + this._readyStateChange(FakeXMLHttpRequest.UNSENT); + this.sendFlag = false; + } + + if (typeof this.onerror === "function") { + this.onerror(); + } + }, + + /* + Duplicates the behavior of native XMLHttpRequest's getResponseHeader function + */ + getResponseHeader: function getResponseHeader(header) { + if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { + return null; + } + + if (/^Set-Cookie2?$/i.test(header)) { + return null; + } + + header = header.toLowerCase(); + + for (var h in this.responseHeaders) { + if (h.toLowerCase() == header) { + return this.responseHeaders[h]; + } + } + + return null; + }, + + /* + Duplicates the behavior of native XMLHttpRequest's getAllResponseHeaders function + */ + getAllResponseHeaders: function getAllResponseHeaders() { + if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { + return ""; + } + + var headers = ""; + + for (var header in this.responseHeaders) { + if (this.responseHeaders.hasOwnProperty(header) && !/^Set-Cookie2?$/i.test(header)) { + headers += header + ": " + this.responseHeaders[header] + "\r\n"; + } + } + + return headers; + }, + + /* + Duplicates the behavior of native XMLHttpRequest's overrideMimeType function + */ + overrideMimeType: function overrideMimeType(mimeType) { + if (typeof mimeType === "string") { + this.forceMimeType = mimeType.toLowerCase(); + } + }, + + + /* + Places a FakeXMLHttpRequest object into the passed + state. + */ + _readyStateChange: function _readyStateChange(state) { + this.readyState = state; + + if (typeof this.onreadystatechange == "function") { + this.onreadystatechange(new _Event("readystatechange")); + } + + this.dispatchEvent(new _Event("readystatechange")); + + if (this.readyState == FakeXMLHttpRequest.DONE) { + this.dispatchEvent(new _Event("load", false, false, this)); + } + if (this.readyState == FakeXMLHttpRequest.UNSENT || this.readyState == FakeXMLHttpRequest.DONE) { + this.dispatchEvent(new _Event("loadend", false, false, this)); + } + }, + + + /* + Sets the FakeXMLHttpRequest object's response headers and + places the object into readyState 2 + */ + _setResponseHeaders: function _setResponseHeaders(headers) { + this.responseHeaders = {}; + + for (var header in headers) { + if (headers.hasOwnProperty(header)) { + this.responseHeaders[header] = headers[header]; + } + } + + if (this.forceMimeType) { + this.responseHeaders['Content-Type'] = this.forceMimeType; + } + + if (this.async) { + this._readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED); + } else { + this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED; + } + }, + + /* + Sets the FakeXMLHttpRequest object's response body and + if body text is XML, sets responseXML to parsed document + object + */ + _setResponseBody: function _setResponseBody(body) { + verifyRequestSent(this); + verifyHeadersReceived(this); + verifyResponseBodyType(body); + + var chunkSize = this.chunkSize || 10; + var index = 0; + this.responseText = ""; + + do { + if (this.async) { + this._readyStateChange(FakeXMLHttpRequest.LOADING); + } + + this.responseText += body.substring(index, index + chunkSize); + index += chunkSize; + } while (index < body.length); + + var type = this.getResponseHeader("Content-Type"); + + if (this.responseText && (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) { + try { + this.responseXML = parseXML(this.responseText); + } catch (e) { + // Unable to parse XML - no biggie + } + } + + if (this.async) { + this._readyStateChange(FakeXMLHttpRequest.DONE); + } else { + this.readyState = FakeXMLHttpRequest.DONE; + } + }, + + /* + Forces a response on to the FakeXMLHttpRequest object. + + This is the public API for faking responses. This function + takes a number status, headers object, and string body: + + ``` + xhr.respond(404, {Content-Type: 'text/plain'}, "Sorry. This object was not found.") + + ``` + */ + respond: function respond(status, headers, body) { + this._setResponseHeaders(headers || {}); + this.status = typeof status == "number" ? status : 200; + this.statusText = httpStatusCodes[this.status]; + this._setResponseBody(body || ""); + } +}; + +for (var property in FakeXMLHttpRequestProto) { + FakeXMLHttpRequest.prototype[property] = FakeXMLHttpRequestProto[property]; +} + +function verifyState(xhr) { + if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { + throw new Error("INVALID_STATE_ERR"); + } + + if (xhr.sendFlag) { + throw new Error("INVALID_STATE_ERR"); + } +} + + +function verifyRequestSent(xhr) { + if (xhr.readyState == FakeXMLHttpRequest.DONE) { + throw new Error("Request done"); + } +} + +function verifyHeadersReceived(xhr) { + if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) { + throw new Error("No headers received"); + } +} + +function verifyResponseBodyType(body) { + if (typeof body != "string") { + var error = new Error("Attempted to respond to fake XMLHttpRequest with " + + body + ", which is not a string."); + error.name = "InvalidBodyException"; + throw error; + } +} +export default FakeXMLHttpRequest; diff --git a/src/phaser.d.ts b/src/phaser.d.ts index a387265..839bee6 100644 --- a/src/phaser.d.ts +++ b/src/phaser.d.ts @@ -3028,7 +3028,14 @@ declare namespace Phaser.Loader.FileTypesManager { * properties into the LoaderPlugin instance. * @param loader The LoaderPlugin to install the types into. */ - function register(loader: Phaser.Loader.LoaderPlugin): void; + function install(loader: Phaser.Loader.LoaderPlugin): void; + + /** + * Static method called directly by the File Types. + * + * The key is a reference to the function used to load the files via the Loader, i.e. `image`. + */ + function register(key: string, factoryFunction: any): void; /** * Removed all associated file types. diff --git a/src/scenes/mainScene.ts b/src/scenes/mainScene.ts index 09f88d2..f251213 100644 --- a/src/scenes/mainScene.ts +++ b/src/scenes/mainScene.ts @@ -5,6 +5,7 @@ import ResetButton from "../sprites/resetButton"; import StatusBar from "../sprites/statusBar"; import _ from "../i18n"; import nearestSolver from "../solvers/nearestSolver"; +import RawSVGFile from "../lib/RawSVGFile"; declare type NeighbourData = { i?: number, @@ -123,7 +124,7 @@ export default class MainScene extends Phaser.Scene { preload(): void { let textureScale = this.r / data.catStepLength; data.textures.forEach(path => { - this.load.svg(path, path, {scale: textureScale}); + this.load.addFile(new RawSVGFile(this.load, path, data.texturesData[path], {scale: textureScale})); }); } diff --git a/webpack.config.js b/webpack.config.js index f8cefe1..f3b7133 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,16 @@ const path = require('path'); const CopyWebpackPlugin = require('copy-webpack-plugin'); +const babelLoader = { + loader: 'babel-loader', + options: { + cacheDirectory: true, + presets: [ + '@babel/preset-env' + ] + } +}; + module.exports = { mode: 'development', devtool: 'source-map', @@ -12,19 +22,29 @@ module.exports = { module: { rules: [ { - test: /\.ts$/, - loader: 'ts-loader', - exclude: '/node_modules/' + test: /\.ts(x?)$/, + exclude: /node_modules/, + use: [ + babelLoader, + { + loader: 'ts-loader' + } + ] }, { - test: /\.m?js$/, - exclude: /(node_modules|bower_components)/, - use: { - loader: 'babel-loader', - options: { - presets: ['@babel/preset-env'] + test: /\.js$/, + exclude: /node_modules/, + use: [ + babelLoader + ] + }, + { + test: /\.svg$/, + use: [ + { + loader: 'raw-loader' } - } + ] } ] }, @@ -33,6 +53,9 @@ module.exports = { { from: 'public' }, + { + from: 'assets' + }, { from: 'node_modules/phaser/dist/phaser.min.js' }