mirror of
https://github.com/judge2020/cloudflare-connectivity-test.git
synced 2026-04-26 10:31:19 +00:00
Turn domain logic into its own component
This commit is contained in:
parent
bef658a6ef
commit
5ed12f6fd6
11 changed files with 443 additions and 198 deletions
8
.editorconfig
Normal file
8
.editorconfig
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
root = true
|
||||
[*.(vue,js,ts)]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
209
package-lock.json
generated
209
package-lock.json
generated
|
|
@ -1073,6 +1073,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"@types/eslint-visitor-keys": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
|
||||
"integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/events": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
|
||||
|
|
@ -1090,6 +1096,12 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz",
|
||||
"integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/minimatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
|
||||
|
|
@ -1114,6 +1126,83 @@
|
|||
"integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/webpack-env": {
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.14.0.tgz",
|
||||
"integrity": "sha512-Fv+0gYJzE/czLoRKq+gnXWr4yBpPM3tO3C8pDLFwqVKlMICQUq5OsxwwFZYDaVr7+L6mgNDp16iOcJHEz3J5RQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.13.0.tgz",
|
||||
"integrity": "sha512-WQHCozMnuNADiqMtsNzp96FNox5sOVpU8Xt4meaT4em8lOG1SrOv92/mUbEHQVh90sldKSfcOc/I0FOb/14G1g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/experimental-utils": "1.13.0",
|
||||
"eslint-utils": "^1.3.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"regexpp": "^2.0.1",
|
||||
"tsutils": "^3.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"regexpp": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
|
||||
"integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
|
||||
"dev": true
|
||||
},
|
||||
"tsutils": {
|
||||
"version": "3.17.1",
|
||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz",
|
||||
"integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.8.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/experimental-utils": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz",
|
||||
"integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.3",
|
||||
"@typescript-eslint/typescript-estree": "1.13.0",
|
||||
"eslint-scope": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.13.0.tgz",
|
||||
"integrity": "sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/eslint-visitor-keys": "^1.0.0",
|
||||
"@typescript-eslint/experimental-utils": "1.13.0",
|
||||
"@typescript-eslint/typescript-estree": "1.13.0",
|
||||
"eslint-visitor-keys": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz",
|
||||
"integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash.unescape": "4.0.1",
|
||||
"semver": "5.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
|
||||
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@vue/babel-helper-vue-jsx-merge-props": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz",
|
||||
|
|
@ -1460,6 +1549,22 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"@vue/cli-plugin-typescript": {
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@vue/cli-plugin-typescript/-/cli-plugin-typescript-3.11.0.tgz",
|
||||
"integrity": "sha512-oL0ctNVvbD7gZr3DDv6gxxWjw0lUrh4sGMk7InCakEooo/790DqZRX6lx9stXEv/+zELkgddcY3hjNEopbJg+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/webpack-env": "^1.13.9",
|
||||
"@vue/cli-shared-utils": "^3.11.0",
|
||||
"fork-ts-checker-webpack-plugin": "^0.5.2",
|
||||
"globby": "^9.2.0",
|
||||
"ts-loader": "^5.3.3",
|
||||
"tslint": "^5.15.0",
|
||||
"webpack": "^4.0.0",
|
||||
"yorkie": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@vue/cli-service": {
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-3.11.0.tgz",
|
||||
|
|
@ -1601,6 +1706,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"@vue/eslint-config-typescript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-4.0.0.tgz",
|
||||
"integrity": "sha512-uSMAMgw4xDgVdZQhpbtJRo8nMV4oOy3Ht8olfOo7xvYFYLMF2JZ1tDRKd9/NSusxA72O2Vma+HzmyzDHg9evcQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/eslint-plugin": "^1.1.0",
|
||||
"@typescript-eslint/parser": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"@vue/preload-webpack-plugin": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.1.tgz",
|
||||
|
|
@ -2674,6 +2789,12 @@
|
|||
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
|
||||
"dev": true
|
||||
},
|
||||
"builtin-modules": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
|
||||
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
|
||||
"dev": true
|
||||
},
|
||||
"builtin-status-codes": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
|
||||
|
|
@ -3472,9 +3593,9 @@
|
|||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
|
||||
"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw=="
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz",
|
||||
"integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A=="
|
||||
},
|
||||
"core-js-compat": {
|
||||
"version": "3.2.1",
|
||||
|
|
@ -4145,6 +4266,12 @@
|
|||
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
|
||||
"dev": true
|
||||
},
|
||||
"diff": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
|
||||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
||||
"dev": true
|
||||
},
|
||||
"diffie-hellman": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
|
||||
|
|
@ -5372,6 +5499,20 @@
|
|||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"fork-ts-checker-webpack-plugin": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-0.5.2.tgz",
|
||||
"integrity": "sha512-a5IG+xXyKnpruI0CP/anyRLAoxWtp3lzdG6flxicANnoSzz64b12dJ7ASAVRrI2OaWwZR2JyBaMHFQqInhWhIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-code-frame": "^6.22.0",
|
||||
"chalk": "^2.4.1",
|
||||
"chokidar": "^2.0.4",
|
||||
"micromatch": "^3.1.10",
|
||||
"minimatch": "^3.0.4",
|
||||
"tapable": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
|
|
@ -7466,6 +7607,12 @@
|
|||
"integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.unescape": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz",
|
||||
"integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.uniq": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
||||
|
|
@ -11426,12 +11573,55 @@
|
|||
"integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
|
||||
"dev": true
|
||||
},
|
||||
"ts-loader": {
|
||||
"version": "5.4.5",
|
||||
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz",
|
||||
"integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.3.0",
|
||||
"enhanced-resolve": "^4.0.0",
|
||||
"loader-utils": "^1.0.2",
|
||||
"micromatch": "^3.1.4",
|
||||
"semver": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
|
||||
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
|
||||
"dev": true
|
||||
},
|
||||
"tslint": {
|
||||
"version": "5.19.0",
|
||||
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.19.0.tgz",
|
||||
"integrity": "sha512-1LwwtBxfRJZnUvoS9c0uj8XQtAnyhWr9KlNvDIdB+oXyT+VpsOAaEhEgKi1HrZ8rq0ki/AAnbGSv4KM6/AfVZw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"builtin-modules": "^1.1.1",
|
||||
"chalk": "^2.3.0",
|
||||
"commander": "^2.12.1",
|
||||
"diff": "^3.2.0",
|
||||
"glob": "^7.1.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"minimatch": "^3.0.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"resolve": "^1.3.2",
|
||||
"semver": "^5.3.0",
|
||||
"tslib": "^1.8.0",
|
||||
"tsutils": "^2.29.0"
|
||||
}
|
||||
},
|
||||
"tsutils": {
|
||||
"version": "2.29.0",
|
||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
|
||||
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.8.1"
|
||||
}
|
||||
},
|
||||
"tty-browserify": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
||||
|
|
@ -11817,6 +12007,11 @@
|
|||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz",
|
||||
"integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ=="
|
||||
},
|
||||
"vue-class-component": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-7.1.0.tgz",
|
||||
"integrity": "sha512-G9152NzUkz0i0xTfhk0Afc8vzdXxDR1pfN4dTwE72cskkgJtdXfrKBkMfGvDuxUh35U500g5Ve4xL8PEGdWeHg=="
|
||||
},
|
||||
"vue-eslint-parser": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz",
|
||||
|
|
@ -11874,6 +12069,14 @@
|
|||
"vue-style-loader": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"vue-property-decorator": {
|
||||
"version": "8.2.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-8.2.2.tgz",
|
||||
"integrity": "sha512-3gRrIeoUtjXvkoMX2stJsVs7805Pa9MXEndnk21ej+sWO7AIc5HF1TKqK0Pox5TEjpO02UbadIF0QWNrx6ZwXQ==",
|
||||
"requires": {
|
||||
"vue-class-component": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"vue-style-loader": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
|
||||
|
|
|
|||
17
package.json
17
package.json
|
|
@ -5,27 +5,31 @@
|
|||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "cross-env NODE_ENV=production vue-cli-service build",
|
||||
"populate": "cross-env NODE_ENV=production tsc misc/populate_list.ts && cross-env node misc/populate_list.js",
|
||||
"lint": "vue-cli-service lint"
|
||||
"lint": "vue-cli-service lint",
|
||||
"populate": "cross-env NODE_ENV=production tsc misc/populate_list.ts && cross-env node misc/populate_list.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.0",
|
||||
"bulma": "^0.7.5",
|
||||
"core-js": "^3.2.1",
|
||||
"core-js": "^2.6.9",
|
||||
"node-sass": "^4.12.0",
|
||||
"sass-loader": "^8.0.0",
|
||||
"vue": "^2.6.10"
|
||||
"vue": "^2.6.10",
|
||||
"vue-class-component": "^7.1.0",
|
||||
"vue-property-decorator": "^8.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.5.5",
|
||||
"@vue/cli-plugin-babel": "^3.11.0",
|
||||
"@vue/cli-plugin-eslint": "^3.11.0",
|
||||
"@vue/cli-service": "^3.11.0",
|
||||
"@vue/eslint-config-typescript": "^4.0.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"cross-env": "^5.2.1",
|
||||
"eslint": "^6.3.0",
|
||||
"eslint-plugin-vue": "^5.2.3",
|
||||
"typescript": "^3.6.2",
|
||||
"@vue/cli-plugin-typescript": "^3.11.0",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
},
|
||||
"eslintConfig": {
|
||||
|
|
@ -35,11 +39,12 @@
|
|||
},
|
||||
"extends": [
|
||||
"plugin:vue/essential",
|
||||
"eslint:recommended"
|
||||
"eslint:recommended",
|
||||
"@vue/typescript"
|
||||
],
|
||||
"rules": {},
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
"parser": "@typescript-eslint/parser"
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<link rel="preload" href="<$= BASE_URL %>iata.json" as="fetch">
|
||||
<title>cloudflare-test.judge.sh</title>
|
||||
</head>
|
||||
|
||||
|
|
|
|||
19
src/App.vue
19
src/App.vue
|
|
@ -1,18 +1,19 @@
|
|||
<template>
|
||||
<div id="app" class="container">
|
||||
<div id="app" class="container">
|
||||
<Main/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Main from './components/Main.vue'
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import Main from './components/Main.vue';
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
@Component({
|
||||
components: {
|
||||
Main
|
||||
}
|
||||
}
|
||||
Main,
|
||||
},
|
||||
})
|
||||
export default class App extends Vue {}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
|||
66
src/components/DomainItem.vue
Normal file
66
src/components/DomainItem.vue
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<div>
|
||||
<p class="heading" v-text="hostname" />
|
||||
<div v-if="finished">
|
||||
<p class="title" v-text="datacenter" />
|
||||
<p class="heading" v-text="airport" />
|
||||
|
||||
<p class="heading">First ping: {{ firstPing }}</p>
|
||||
<p class="heading">Second ping: {{ secondPing }}</p>
|
||||
</div>
|
||||
<div v-if="broken">
|
||||
<p>Likely not a Cloudflare website, or not proxied</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Vue, Component, Prop } from "vue-property-decorator";
|
||||
import Axios from "axios";
|
||||
@Component
|
||||
export default class DomainItem extends Vue {
|
||||
// @ts-ignore
|
||||
@Prop(String) readonly hostname: string;
|
||||
finished = false;
|
||||
broken = false;
|
||||
datacenter = "";
|
||||
airport = "";
|
||||
firstPing = 0;
|
||||
secondPing = 0;
|
||||
mounted() {
|
||||
this.loadHostname(this.hostname)
|
||||
.then(datacenter => {
|
||||
this.datacenter = datacenter;
|
||||
// @ts-ignore
|
||||
this.airport = this.$parent.getAirport(datacenter);
|
||||
})
|
||||
.then(() => this.loadHostname(this.hostname, 1))
|
||||
.then(() => {
|
||||
this.firstPing = this.loadPing(this.hostname, 0);
|
||||
this.secondPing = this.loadPing(this.hostname, 1);
|
||||
this.finished = true;
|
||||
})
|
||||
.catch(() => {
|
||||
this.broken = true;
|
||||
});
|
||||
}
|
||||
|
||||
loadPing(hostname: string, loadNumber = 0) {
|
||||
let timing = performance
|
||||
.getEntriesByType("resource")
|
||||
.filter(timing => timing.name.includes(hostname))
|
||||
.filter(timing => timing.name.includes(`load=${loadNumber}`))[0];
|
||||
// @ts-ignore
|
||||
return Math.floor(timing.responseEnd - timing.startTime);
|
||||
}
|
||||
loadHostname(hostname: string, loadNumber = 0): Promise<string> {
|
||||
return Axios.get(
|
||||
`https://${hostname}/cdn-cgi/trace?load=${loadNumber}`
|
||||
).then(response => {
|
||||
return response.data
|
||||
.split("\n")
|
||||
.map((n: string) => n.split("="))
|
||||
.filter((element: string[]) => element[0] == "colo")[0][1];
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -2,10 +2,14 @@
|
|||
<div class="main-content">
|
||||
<div class="container has-text-centered">
|
||||
<h1 class="title">Cloudflare datacenter reachability</h1>
|
||||
|
||||
<h2 class="subtitle"><a href="https://github.com/judge2020/cloudflare-connectivity-test/wiki/Explanation">Explanation</a></h2>
|
||||
|
||||
<h2 class="subtitle">
|
||||
<a
|
||||
href="https://github.com/judge2020/cloudflare-connectivity-test/wiki/Explanation"
|
||||
>Explanation</a>
|
||||
</h2>
|
||||
<p class="subtitle">Test your website:</p>
|
||||
<form @submit="loadTestHostname(testHostname)">
|
||||
<form @submit.prevent="loadTestHostname(testHostname)">
|
||||
<div class="field has-addons has-addons-centered">
|
||||
<div class="control">
|
||||
<input
|
||||
|
|
@ -13,7 +17,6 @@
|
|||
type="text"
|
||||
placeholder="example.com"
|
||||
v-model="testHostname"
|
||||
@blur="loadTestHostname(testHostname)"
|
||||
/>
|
||||
</div>
|
||||
<div class="control">
|
||||
|
|
@ -22,15 +25,8 @@
|
|||
</div>
|
||||
</form>
|
||||
|
||||
<div class="domain-item" v-if="testHostname">
|
||||
<p class="heading" v-text="testHostname" />
|
||||
<div v-if="testHostname in finished">
|
||||
<p class="title" v-text="finished[testHostname]" />
|
||||
<p class="heading" v-text="iata[finished[testHostname]]" />
|
||||
<p class="heading">First ping: {{ timingsFirst[testHostname] }}</p>
|
||||
<p class="heading">Second ping: {{ timingsSecond[testHostname] }}</p>
|
||||
</div>
|
||||
<p v-show="testHostname in broken">Likely not a Cloudflare website!</p>
|
||||
<div class="domain-item" v-if="testHostname" :key="testHostname">
|
||||
<domain-item :hostname="testHostname" />
|
||||
</div>
|
||||
<hr />
|
||||
</div>
|
||||
|
|
@ -39,53 +35,28 @@
|
|||
<div class="column">
|
||||
<p class="title">FREE</p>
|
||||
<div class="domain-item" v-for="(site, index) in free" :key="index">
|
||||
<p class="heading" v-text="site" />
|
||||
<div v-if="site in finished">
|
||||
<p class="title" v-text="finished[site]" />
|
||||
<p class="heading" v-text="iata[finished[site]]" />
|
||||
<p class="heading">First ping: {{ timingsFirst[site] }}</p>
|
||||
<p class="heading">Second ping: {{ timingsSecond[site] }}</p>
|
||||
</div>
|
||||
<domain-item :hostname="site" />
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
<div class="column list-domains">
|
||||
<p class="title">PRO</p>
|
||||
<div class="domain-item" v-for="(site, index) in pro" :key="index">
|
||||
<p class="heading" v-text="site" />
|
||||
<div v-if="site in finished">
|
||||
<p class="title" v-text="finished[site]" />
|
||||
<p class="heading" v-text="iata[finished[site]]" />
|
||||
<p class="heading">First ping: {{ timingsFirst[site] }}</p>
|
||||
<p class="heading">Second ping: {{ timingsSecond[site] }}</p>
|
||||
</div>
|
||||
<domain-item :hostname="site" />
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
<div class="column list-domains">
|
||||
<p class="title">BUSINESS</p>
|
||||
<div class="domain-item" v-for="(site, index) in business" :key="index">
|
||||
<p class="heading" v-text="site" />
|
||||
<div v-if="site in finished">
|
||||
<p class="title" v-text="finished[site]" />
|
||||
<p class="heading" v-text="iata[finished[site]]" />
|
||||
<p class="heading">First ping: {{ timingsFirst[site] }}</p>
|
||||
<p class="heading">Second ping: {{ timingsSecond[site] }}</p>
|
||||
</div>
|
||||
<domain-item :hostname="site" />
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
<div class="column list-domains">
|
||||
<p class="title">ENTERPRISE</p>
|
||||
<div class="domain-item" v-for="(site, index) in enterprise" :key="index">
|
||||
<p class="heading" v-text="site" />
|
||||
<div v-if="site in finished">
|
||||
<p class="title" v-text="finished[site]" />
|
||||
<p class="heading" v-text="iata[finished[site]]" />
|
||||
|
||||
<p class="heading">First ping: {{ timingsFirst[site] }}</p>
|
||||
<p class="heading">Second ping: {{ timingsSecond[site] }}</p>
|
||||
</div>
|
||||
<domain-item :hostname="site" />
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -112,153 +83,89 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import { Vue, Component, Prop } from "vue-property-decorator";
|
||||
import Axios from "axios";
|
||||
export default {
|
||||
name: "Main",
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
testHostname: "",
|
||||
iata: [],
|
||||
timingsFirst: [],
|
||||
timingsSecond: [],
|
||||
finished: [],
|
||||
broken: [],
|
||||
free: [
|
||||
"judge2020.com",
|
||||
"domjh.net",
|
||||
"digital.com",
|
||||
"firing.it",
|
||||
"www.shoutmeloud.com",
|
||||
"judge2020.me",
|
||||
"cloudeereviews.com"
|
||||
],
|
||||
pro: [
|
||||
"js.org",
|
||||
"git-scm.com",
|
||||
"nodejs.org",
|
||||
"cdnjs.com",
|
||||
"getbootstrap.com",
|
||||
"reactjs.org",
|
||||
"html5boilerplate.com",
|
||||
"yarnpkg.com",
|
||||
"d3js.org"
|
||||
],
|
||||
business: [
|
||||
"judge.sh",
|
||||
"www.mozilla.org",
|
||||
"domjh.com",
|
||||
"manfredi.io",
|
||||
"corporateclash.net",
|
||||
"sontusdatos.org",
|
||||
"www.opentech.fund",
|
||||
"cpj.org",
|
||||
"www.amnestyusa.org",
|
||||
"cdt.org",
|
||||
"www.counterextremism.com",
|
||||
"www.ndi.org",
|
||||
"www.findlaw.com",
|
||||
"www.codeguard.com",
|
||||
"www.techagainstterrorism.org",
|
||||
"www.thetrevorproject.org"
|
||||
],
|
||||
enterprise: [
|
||||
"cloudflare.com",
|
||||
"cdnjs.cloudflare.com",
|
||||
"medium.com",
|
||||
"discordapp.com",
|
||||
"www.zendesk.com",
|
||||
"ghost.io",
|
||||
"unpkg.com",
|
||||
"www.loc.gov",
|
||||
"www.artstation.com",
|
||||
"www.digitalocean.com",
|
||||
"quizlet.com",
|
||||
"i.gyazo.com"
|
||||
]
|
||||
};
|
||||
},
|
||||
import DomainItem from "./DomainItem";
|
||||
@Component({
|
||||
components: {
|
||||
DomainItem
|
||||
}
|
||||
})
|
||||
export default class Main extends Vue {
|
||||
iata = [];
|
||||
free = [
|
||||
"judge2020.com",
|
||||
"domjh.net",
|
||||
"digital.com",
|
||||
"firing.it",
|
||||
"www.shoutmeloud.com",
|
||||
"judge2020.me",
|
||||
"cloudeereviews.com"
|
||||
];
|
||||
pro = [
|
||||
"js.org",
|
||||
"git-scm.com",
|
||||
"nodejs.org",
|
||||
"cdnjs.com",
|
||||
"getbootstrap.com",
|
||||
"reactjs.org",
|
||||
"html5boilerplate.com",
|
||||
"yarnpkg.com",
|
||||
"d3js.org"
|
||||
];
|
||||
business = [
|
||||
"judge.sh",
|
||||
"www.mozilla.org",
|
||||
"domjh.com",
|
||||
"manfredi.io",
|
||||
"corporateclash.net",
|
||||
"sontusdatos.org",
|
||||
"www.opentech.fund",
|
||||
"cpj.org",
|
||||
"www.amnestyusa.org",
|
||||
"cdt.org",
|
||||
"www.counterextremism.com",
|
||||
"www.ndi.org",
|
||||
"www.findlaw.com",
|
||||
"www.codeguard.com",
|
||||
"www.techagainstterrorism.org",
|
||||
"www.thetrevorproject.org"
|
||||
];
|
||||
enterprise = [
|
||||
"cloudflare.com",
|
||||
"cdnjs.cloudflare.com",
|
||||
"medium.com",
|
||||
"discordapp.com",
|
||||
"www.zendesk.com",
|
||||
"ghost.io",
|
||||
"unpkg.com",
|
||||
"www.loc.gov",
|
||||
"www.artstation.com",
|
||||
"www.digitalocean.com",
|
||||
"quizlet.com",
|
||||
"i.gyazo.com"
|
||||
];
|
||||
mounted() {
|
||||
this.preloadAirports();
|
||||
this.free
|
||||
.concat(this.pro, this.business, this.enterprise)
|
||||
.forEach(hostname => {
|
||||
this.loadHostname(hostname, 0)
|
||||
.then(() => {
|
||||
// load UI with ping data
|
||||
this.loadPing(hostname, 0);
|
||||
// begin promise for second ping (TCP and DNS overhead should be gone)
|
||||
return this.loadHostname(hostname, 1);
|
||||
})
|
||||
.then(() => {
|
||||
// load UI with second ping data
|
||||
this.loadPing(hostname, 1);
|
||||
});
|
||||
});
|
||||
|
||||
// load query string hostname
|
||||
if (location.hash) {
|
||||
this.testHostname = location.hash.replace("#", "");
|
||||
this.loadTestHostname(this.testHostname);
|
||||
this.$forceUpdate();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadPing(hostname, loadNumber = 0) {
|
||||
performance
|
||||
.getEntriesByType("resource")
|
||||
.filter(timing => timing.name.includes(hostname))
|
||||
.filter(timing => timing.name.includes(`load=${loadNumber}`))
|
||||
.forEach(timing => {
|
||||
if (loadNumber == 0) {
|
||||
this.timingsFirst[new URL(timing.name).hostname] = Math.floor(
|
||||
timing.responseEnd - timing.startTime
|
||||
);
|
||||
} else {
|
||||
this.timingsSecond[new URL(timing.name).hostname] = Math.floor(
|
||||
timing.responseEnd - timing.startTime
|
||||
);
|
||||
}
|
||||
});
|
||||
this.$forceUpdate();
|
||||
},
|
||||
preloadAirports() {
|
||||
Axios.get("/iata.json").then(response => {
|
||||
this.iata = response.data;
|
||||
});
|
||||
},
|
||||
loadTestHostname(hostname) {
|
||||
history.replaceState(
|
||||
"",
|
||||
"",
|
||||
hostname.includes("#") ? hostname : "#" + hostname
|
||||
);
|
||||
this.loadHostname(hostname, 0)
|
||||
.then(() => {
|
||||
this.loadPing(hostname, 0);
|
||||
return this.loadHostname(hostname, 1);
|
||||
})
|
||||
.then(() => {
|
||||
this.loadPing(hostname, 1);
|
||||
});
|
||||
},
|
||||
loadHostname(hostname, loadNumber = 0) {
|
||||
return Axios.get(
|
||||
`https://${hostname}/cdn-cgi/trace?load=${loadNumber}`
|
||||
).then(response => {
|
||||
response.data
|
||||
.split("\n")
|
||||
.map(n => n.split("="))
|
||||
.forEach(element => {
|
||||
if (element[0] == "colo") {
|
||||
Vue.set(this.finished, hostname, element[1]);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
loadTestHostname() {
|
||||
this.$forceUpdate();
|
||||
}
|
||||
getAirport(code) {
|
||||
return this.iata[code];
|
||||
}
|
||||
preloadAirports() {
|
||||
Axios.get("/iata.json").then(response => {
|
||||
this.iata = response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
|
|
|
|||
13
src/shims-tsx.d.ts
vendored
Normal file
13
src/shims-tsx.d.ts
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import Vue, { VNode } from 'vue'
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
// tslint:disable no-empty-interface
|
||||
interface Element extends VNode {}
|
||||
// tslint:disable no-empty-interface
|
||||
interface ElementClass extends Vue {}
|
||||
interface IntrinsicElements {
|
||||
[elem: string]: any
|
||||
}
|
||||
}
|
||||
}
|
||||
4
src/shims-vue.d.ts
vendored
Normal file
4
src/shims-vue.d.ts
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
declare module '*.vue' {
|
||||
import Vue from 'vue'
|
||||
export default Vue
|
||||
}
|
||||
39
tsconfig.json
Normal file
39
tsconfig.json
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"importHelpers": true,
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
"webpack-env"
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue