From 120b48953820f694d6f1a0eb99decf78cd02c4b8 Mon Sep 17 00:00:00 2001 From: jaywcjlove <398188662@qq.com> Date: Mon, 30 Dec 2019 16:04:52 +0800 Subject: [PATCH] init project. --- .github/workflows/ci.yml | 33 ++++++++ .gitignore | 14 ++++ .kktrc.ts | 9 +++ README.md | 4 + data.json | 161 +++++++++++++++++++++++++++++++++++++++ package.json | 46 +++++++++++ public/favicon.ico | Bin 0 -> 5430 bytes public/index.html | 15 ++++ src/app/App.module.less | 37 +++++++++ src/app/App.tsx | 51 +++++++++++++ src/app/Google.tsx | 14 ++++ src/index.css | 18 +++++ src/index.tsx | 13 ++++ src/serviceWorker.ts | 143 ++++++++++++++++++++++++++++++++++ src/types/declare.d.ts | 59 ++++++++++++++ tsconfig.json | 32 ++++++++ 16 files changed, 649 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .kktrc.ts create mode 100644 README.md create mode 100644 data.json create mode 100644 package.json create mode 100644 public/favicon.ico create mode 100644 public/index.html create mode 100644 src/app/App.module.less create mode 100644 src/app/App.tsx create mode 100644 src/app/Google.tsx create mode 100644 src/index.css create mode 100644 src/index.tsx create mode 100644 src/serviceWorker.ts create mode 100644 src/types/declare.d.ts create mode 100644 tsconfig.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..621429b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,33 @@ +name: GitHub Actions Build and Deploy +on: + push: + branches: + - master +jobs: + build-deploy: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@master + + - name: Setup Node + uses: actions/setup-node@v1 + with: + node-version: '10.x' + + # - name: Cache dependencies + # uses: actions/cache@v1 + # with: + # path: ~/.npm + # key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + # restore-keys: | + # ${{ runner.os }}-node- + + - run: npm install + - run: npm run build + + - name: Build and Deploy + uses: peaceiris/actions-gh-pages@v2 + env: + ACTIONS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }} + PUBLISH_BRANCH: gh-pages + PUBLISH_DIR: ./build \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..da07ff8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +node_modules +build +npm-debug.log* +package-lock.json +.DS_Store +.cache +.vscode + +*.bak +*.tem +*.temp +#.swp +*.*~ +~*.* diff --git a/.kktrc.ts b/.kktrc.ts new file mode 100644 index 0000000..b21f0b4 --- /dev/null +++ b/.kktrc.ts @@ -0,0 +1,9 @@ +import path from 'path'; + +export const moduleScopePluginOpts = [ + path.resolve(process.cwd(), 'data.json'), +]; + +export const loaderOneOf = [ + [require.resolve('@kkt/loader-less'), {}], +]; diff --git a/README.md b/README.md new file mode 100644 index 0000000..d177eed --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ + +This is the Google Mirror Index. + +https://jaywcjlove.github.io/google \ No newline at end of file diff --git a/data.json b/data.json new file mode 100644 index 0000000..e6c3ad7 --- /dev/null +++ b/data.json @@ -0,0 +1,161 @@ +{ + "update": "", + "data": [ + { "url": "https://www.teoma.com", "type": "web", "status": 200 }, + { "url": "https://intelme.com", "type": "web", "status": 200 }, + { "url": "https://skyn3t.in/srx", "type": "web", "status": 200 }, + { "url": "https://suche.dasnetzundich.de", "type": "web", "status": 200 }, + { "url": "https://searx.com.au", "type": "web", "status": 200 }, + { "url": "https://burtrum.org/searx", "type": "web", "status": 200 }, + { "url": "https://roteserver.de/searx", "type": "web", "status": 200 }, + { "url": "https://srx.sx", "type": "web", "status": 200 }, + { "url": "https://search.paulla.asso.fr", "type": "web", "status": 200 }, + { "url": "https://search.spaeth.me", "type": "web", "status": 200 }, + { "url": "https://seeks.hsbp.org", "type": "web", "status": 200 }, + { "url": "https://searx.linux.pizza", "type": "web", "status": 200 }, + { "url": "https://searx.gotrust.de", "type": "web", "status": 200 }, + { "url": "https://trovu.komun.org", "type": "web", "status": 200 }, + { "url": "http://so.hiqq.com.cn", "type": "scholar", "status": 200 }, + { "url": "https://sci-hub.org.cn", "type": "scholar", "status": 200 }, + { "url": "https://scholar.123admin.com", "type": "scholar", "status": 200 }, + { "url": "http://www.ndtsg.com", "type": "scholar", "status": 200 }, + { "url": "https://www.80xueshu.com", "type": "scholar", "status": 200 }, + { "url": "https://xue.glgoo.org", "type": "scholar", "status": 200 }, + { "url": "https://s0.unllu.com/", "type": "scholar", "status": 200 }, + { "url": "https://xs.zb-welding.com/scholar", "type": "scholar", "status": 200 }, + { "url": "https://searx.operationtulip.com", "type": "web", "status": 200 }, + { "url": "https://search.st8.at", "type": "web", "status": 200 }, + { "url": "https://mijisou.com", "type": "web", "status": 200 }, + { "url": "https://haku.ahmia.fi", "type": "web", "status": 200 }, + { "url": "https://google.nekoemtp.workers.dev", "type": "web", "status": 200 }, + { "url": "http://baidu01.puataiwan.com", "type": "web", "status": 200 }, + { "url": "https://gg.smiling.workers.dev", "type": "web", "status": 200 }, + { "url": "https://www.gosearchresults.com", "type": "web", "status": 200 }, + { "url": "https://lite.qwant.com", "type": "web", "status": 200 }, + { "url": "https://seeres.com", "type": "web", "status": 200 }, + { "url": "https://1.52qu.xyz", "type": "web", "status": 200 }, + { "url": "https://guge.one", "type": "web", "status": 200 }, + { "url": "https://nav.hiqq.com.cn/twy", "type": "web", "status": 200 }, + { "url": "https://g.luciaz.me", "type": "web", "status": 200 }, + { "url": "https://searx.xyz", "type": "web", "status": 200 }, + { "url": "https://www.kuaimen.bid", "type": "web", "status": 200 }, + { "url": "https://4.52qu.xyz", "type": "web", "status": 200 }, + { "url": "https://b.glgoo.top/scholar", "type": "web", "status": 200 }, + { "url": "https://c.glgoo.top/scholar", "type": "web", "status": 200 }, + { "url": "https://cc.glgoo.top/scholar", "type": "web", "status": 200 }, + { "url": "https://guge.schove.com", "type": "web", "status": 200 }, + { "url": "http://so.hiqq.com.cn", "type": "web", "status": 200 }, + { "url": "http://nav.hiqq.com.cn/twy", "type": "web", "status": 200 }, + { "url": "https://searx.be", "type": "web", "status": 200 }, + { "url": "https://searx.elukerio.org", "type": "web", "status": 200 }, + { "url": "https://searx.libmail.eu", "type": "web", "status": 200 }, + { "url": "https://search.snopyta.org", "type": "web", "status": 200 }, + { "url": "https://searx.win", "type": "web", "status": 200 }, + { "url": "https://search.galaxy.cat", "type": "web", "status": 200 }, + { "url": "https://searx.info", "type": "web", "status": 200 }, + { "url": "https://searx.tuxcloud.net", "type": "web", "status": 200 }, + { "url": "https://searx.prvcy.eu", "type": "web", "status": 200 }, + { "url": "https://search.stinpriza.org", "type": "web", "status": 200 }, + { "url": "https://searx.site", "type": "web", "status": 200 }, + { "url": "https://searx.mastodontech.de", "type": "web", "status": 200 }, + { "url": "https://searx.solusar.de", "type": "web", "status": 200 }, + { "url": "https://search.mdosch.de", "type": "web", "status": 200 }, + { "url": "https://searx.decatec.de", "type": "web", "status": 200 }, + { "url": "https://searx.dresden.network", "type": "web", "status": 200 }, + { "url": "https://search.disroot.org", "type": "web", "status": 200 }, + { "url": "https://rapu.nz", "type": "web", "status": 200 }, + { "url": "https://searx.pofilo.fr", "type": "web", "status": 200 }, + { "url": "https://unmonito.red", "type": "web", "status": 200 }, + { "url": "https://searx.canox.net", "type": "web", "status": 200 }, + { "url": "https://search.modalogi.com", "type": "web", "status": 200 }, + { "url": "https://searx.pwoss.org", "type": "web", "status": 200 }, + { "url": "https://searx.hlfh.space", "type": "web", "status": 200 }, + { "url": "https://searx.xyz", "type": "web", "status": 200 }, + { "url": "https://searx.nnto.net", "type": "web", "status": 200 }, + { "url": "https://search.biboumail.fr", "type": "web", "status": 200 }, + { "url": "https://www.perfectpixel.de/searx", "type": "web", "status": 200 }, + { "url": "https://searx.zareldyn.net", "type": "web", "status": 200 }, + { "url": "https://searx.li", "type": "web", "status": 200 }, + { "url": "https://searx.envs.net", "type": "web", "status": 200 }, + { "url": "https://dc.ax", "type": "web", "status": 200 }, + { "url": "https://wtf.roflcopter.fr/searx", "type": "web", "status": 200 }, + { "url": "https://s.cmd.gg", "type": "web", "status": 200 }, + { "url": "https://searx.anongoth.pl", "type": "web", "status": 200 }, + { "url": "https://searx.fr32k.de", "type": "web", "status": 200 }, + { "url": "https://searx.nakhan.net", "type": "web", "status": 200 }, + { "url": "https://search.datensturm.net", "type": "web", "status": 200 }, + { "url": "https://searx.openpandora.org", "type": "web", "status": 200 }, + { "url": "https://spot.ecloud.global", "type": "web", "status": 200 }, + { "url": "https://search.lgbtq.cool", "type": "web", "status": 200 }, + { "url": "https://suche.uferwerk.org", "type": "web", "status": 200 }, + { "url": "https://searx.openhoofd.nl", "type": "web", "status": 200 }, + { "url": "https://searx.ru", "type": "web", "status": 200 }, + { "url": "https://searx.targaryen.house", "type": "web", "status": 200 }, + { "url": "https://le-dahut.com/searx", "type": "web", "status": 200 }, + { "url": "https://search.moravit.com", "type": "web", "status": 200 }, + { "url": "https://zoek.anchel.nl", "type": "web", "status": 200 }, + { "url": "https://search.seds.nl", "type": "web", "status": 200 }, + { "url": "https://openworlds.info", "type": "web", "status": 200 }, + { "url": "https://dynabyte.ca", "type": "web", "status": 200 }, + { "url": "https://searx.foo.li", "type": "web", "status": 200 }, + { "url": "https://www.skyn3t.in/search", "type": "web", "status": 200 }, + { "url": "https://searx.me", "type": "web", "status": 200 }, + { "url": "https://www.searx.de", "type": "web", "status": 200 }, + { "url": "https://ai.deafpray.wtf/searx", "type": "web", "status": 200 }, + { "url": "https://searx.mxchange.org", "type": "web", "status": 200 }, + { "url": "https://timdor.noip.me/searx", "type": "web", "status": 200 }, + { "url": "https://search.activemail.de", "type": "web", "status": 200 }, + { "url": "https://bamboozle.it", "type": "web", "status": 200 }, + { "url": "https://searx.ouahpiti.info", "type": "web", "status": 200 }, + { "url": "https://searx.laquadrature.net", "type": "web", "status": 200 }, + { "url": "https://search.poal.co", "type": "web", "status": 200 }, + { "url": "https://null.media", "type": "web", "status": 200 }, + { "url": "https://search.dominikschroeck.de", "type": "web", "status": 200 }, + { "url": "https://searx.lynnesbian.space", "type": "web", "status": 200 }, + { "url": "https://searx.john-at-me.net", "type": "web", "status": 200 }, + { "url": "https://search.anonymize.com", "type": "web", "status": 200 }, + { "url": "https://search.azkware.net", "type": "web", "status": 200 }, + { "url": "https://searx.everdot.org", "type": "web", "status": 200 }, + { "url": "https://jsearch.pw", "type": "web", "status": 200 }, + { "url": "https://www.searxs.eu", "type": "web", "status": 200 }, + { "url": "https://search.nebulacentre.net", "type": "web", "status": 200 }, + { "url": "https://search.fossdaily.xyz", "type": "web", "status": 200 }, + { "url": "https://search.wxzm.sx", "type": "web", "status": 200 }, + { "url": "https://search.gibberfish.org", "type": "web", "status": 200 }, + { "url": "https://goso.ga", "type": "web", "status": 200 }, + { "url": "https://searx.lavatech.top", "type": "web", "status": 200 }, + { "url": "https://searchx.mobi", "type": "web", "status": 200 }, + { "url": "https://searx.run", "type": "web", "status": 200 }, + { "url": "https://searx.wegeeks.win", "type": "web", "status": 200 }, + { "url": "https://searx.world", "type": "web", "status": 200 }, + + { "url": "https://g2.wen.lu", "type": "web", "status": 400 }, + { "url": "http://gc.ihuan.me", "type": "web", "status": 400 }, + { "url": "http://ggss.cf", "type": "web", "status": 400 }, + { "url": "http://hao.cytbj.com", "type": "web", "status": 400 }, + { "url": "http://jgoproxy.tk", "type": "web", "status": 400 }, + { "url": "http://s.8090st.com", "type": "web", "status": 400 }, + { "url": "https://www.wacao.org", "type": "web", "status": 400 }, + { "url": "http://www.g363.com", "type": "web", "status": 400 }, + { "url": "http://g.helloit.info", "type": "web", "status": 400 }, + { "url": "https://g.jikewenku.cn", "type": "web", "status": 400 }, + { "url": "https://www.guge.xxx", "type": "web", "status": 400 }, + { "url": "https://g.libnull.com", "type": "web", "status": 400 }, + { "url": "http://ssdao.cdjltz.com", "type": "web", "status": 400 }, + { "url": "https://global.gogfw.com", "type": "web", "status": 400 }, + { "url": "https://www.onk6.com", "type": "web", "status": 400 }, + { "url": "http://www.hntvchina.com", "type": "web", "status": 400 }, + { "url": "https://g.zrj766.com", "type": "web", "status": 400 }, + { "url": "https://g.alexyang.me", "type": "web", "status": 400 }, + { "url": "https://ggso.in", "type": "web", "status": 400 }, + { "url": "http://www.bjgong.tk", "type": "web", "status": 400 }, + { "url": "http://scholar.hntvchina.com", "type": "web", "status": 400 }, + { "url": "https://ggss.ml", "type": "web", "status": 400 }, + { "url": "https://fuckgfw.ggss.cf", "type": "web", "status": 400 }, + { "url": "https://g.jikewenku.cn", "type": "web", "status": 400 }, + { "url": "http://www.mrba.com.cn", "type": "web", "status": 400 }, + { "url": "http://hi18.cn", "type": "web", "status": 400 }, + { "url": "http://www.gusou.co", "type": "web", "status": 400 }, + { "url": "https://fengfei.org", "type": "web", "status": 400 } + ] +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..ad7a0c9 --- /dev/null +++ b/package.json @@ -0,0 +1,46 @@ +{ + "name": "guge", + "version": "1.0.0", + "description": "This is the Google Mirror Index.", + "homepage": "https://github.com/jaywcjlove/google", + "private": true, + "scripts": { + "prepare": "npm run build", + "start": "kkt start", + "build": "kkt build" + }, + "repository": { + "type": "git", + "url": "https://github.com/jaywcjlove/google.git" + }, + "author": "", + "license": "MIT", + "dependencies": {}, + "devDependencies": { + "@kkt/loader-less": "^5.2.2", + "@types/classnames": "^2.2.8", + "@types/jest": "^24.0.23", + "@types/react": "^16.9.13", + "@types/react-dom": "^16.9.4", + "@uiw/react-github-corners": "^1.1.2", + "classnames": "^2.2.6", + "kkt": "5.2.1", + "react": "^16.12.0", + "react-dom": "^16.12.0" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..82339b3b1dbbcf4550b737faf99c7774196fb8cb GIT binary patch literal 5430 zcmcgwX>3$g6n=;X+3|<}Oe_lM4}(N0C5Rv{W&J^*wo?RyAcBe}5&;u}0*OVy7L=Ay zXf2DCb|BCKWlMolQL5~P(pm(H?9=IVT4p+(_4u9l<_-5P?F_|ulQZ|;bI*6abC-9Q zk)%%2V^W_!67o1{&f}6aK$4`mIHg_yeFk(dLWd$O6g@IYf<9UzqCvr6a2=!u;tfkR z^2|^uG_Wl^+PcCf8~An;Y_eeRr06G%J;p#^&`W#&+C~cwO(V;@`5-Yh&vvE5}7=D}8hx zzSiZsXwv%)bp1v^?_?0K0r<(~hP$>PS!Oz9AM8gja~C)xcwp8umJ^iSP?sl_;1=C2bSk~ zIqV~QVl4FGK3B%d6U`1WoP*7Cv2eqV&l#JUPn+vD?W*2P%gW}`tm3iqo|;^kKr@RH zY4PD%lwX-eR~DX!e8cgN$vb75Ey(67=P7uRfkXkImj>G|>W zXT}Kf9?R3aA>af^1Lr9{g9Fh;$_Uj zO$l^k#i+>nrk<;6AmH+WGxBYsuGwFCoxNu==CgNCpi{TXRX2vbuCbO1if2-j?re3h zNurQfd;WoQ1CIgX=!LSTaoLI0hQ7}~IF*{c56&3_xvB{G$g^!>r0?n(@2eryDTfPDUI#V#9aW zg7STZ?<{>w_Rz$F;Z%C1NHmG5>^o7Q;pZ4a&N~_`xcMwODJn;w2}JlghJocb$*)|6 zM6;;npzW%G-(M|XWg}Q{^O>a?*k{U>`xbMvSSk&7lL(#*;uuFO`zov&EV%jH)Lg2% zgzt+g|Kh(*E?9z>Xq;lZelGwwpWpu*zwftvA#(Y?#rzGTQa}Ew7yi5P_g5Visdyjc z@z<=s#M9dK*LSCv{F%%UeQ!jK5^1Z6D)T6KJ>Z&m?k z4s&xt950}*S?DE)JO+L>j?`HWTD#FjJNJ5MSBZx*QRcUd+Rk}eMzi`HHqe9156*rH zyYdU2@^}@jH*Irke2V^KDKA~wEO>iR1lLNDo6Cr&JM>i#tdtUu!-(<5xroL;azZ^F zI@+pt$MaqZF3lTHjRpDvXs_3UZruscS4*2{$lJ!Zr#=q0S@2C0F-D)@+om6Pm0Qix z&hJD+4D5^7IInszx) + + + + + + + Google 镜像 + + + +
+ + + diff --git a/src/app/App.module.less b/src/app/App.module.less new file mode 100644 index 0000000..066069b --- /dev/null +++ b/src/app/App.module.less @@ -0,0 +1,37 @@ +.warpper { + padding: 0; +} + +.header { + padding: 25px 10px 10px 25px; +} + +.body { + padding: 12px 10px 60px 18px; + font-size: 14px; + table { + border-spacing: 0; + border-collapse: collapse; + } + thead th, tbody td { + padding: 3px 10px; + line-height: 21px; + } + thead th { + text-align: left; + } + tbody tr { + background-color: transparent; + transition: all .3s; + } + tbody tr:hover { + background-color: #f1f1f1; + } +} + +.notFound { + color: #797979; + a { + color: #797979; + } +} \ No newline at end of file diff --git a/src/app/App.tsx b/src/app/App.tsx new file mode 100644 index 0000000..ce46867 --- /dev/null +++ b/src/app/App.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import classnames from 'classnames'; +import GitHubCorners from '@uiw/react-github-corners'; +import styles from './App.module.less'; +import Google from './Google'; +import data from '../../data.json'; + + +interface DataItem { + status?: number; + type?: 'web' | 'scholar'; + url: string; +} + +const App = () => ( +
+ +
+ +
+ +
+); + +export default App; diff --git a/src/app/Google.tsx b/src/app/Google.tsx new file mode 100644 index 0000000..72a298f --- /dev/null +++ b/src/app/Google.tsx @@ -0,0 +1,14 @@ +import React from 'react'; + +export default () => { + return ( + + + + + + + + + ); +} \ No newline at end of file diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..69f61dd --- /dev/null +++ b/src/index.css @@ -0,0 +1,18 @@ +body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + + +a { + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..738fed9 --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './app/App'; +import './index.css'; +import * as serviceWorker from './serviceWorker'; + +ReactDOM.render(, document.getElementById('root')); + + +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: https://bit.ly/CRA-PWA +serviceWorker.unregister(); diff --git a/src/serviceWorker.ts b/src/serviceWorker.ts new file mode 100644 index 0000000..15d90cb --- /dev/null +++ b/src/serviceWorker.ts @@ -0,0 +1,143 @@ +// This optional code is used to register a service worker. +// register() is not called by default. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. + +// To learn more about the benefits of this model and instructions on how to +// opt-in, read https://bit.ly/CRA-PWA + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.1/8 is considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) +); + +type Config = { + onSuccess?: (registration: ServiceWorkerRegistration) => void; + onUpdate?: (registration: ServiceWorkerRegistration) => void; +}; + +export function register(config?: Config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL( + (process as { env: { [key: string]: string } }).env.PUBLIC_URL, + window.location.href + ); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://bit.ly/CRA-PWA' + ); + }); + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config); + } + }); + } +} + +function registerValidSW(swUrl: string, config?: Config) { + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' + ); + + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration); + } + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch(error => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl: string, config?: Config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type'); + if ( + response.status === 404 || + (contentType != null && contentType.indexOf('javascript') === -1) + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config); + } + }) + .catch(() => { + console.log( + 'No internet connection found. App is running in offline mode.' + ); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready.then(registration => { + registration.unregister(); + }); + } +} diff --git a/src/types/declare.d.ts b/src/types/declare.d.ts new file mode 100644 index 0000000..10ec815 --- /dev/null +++ b/src/types/declare.d.ts @@ -0,0 +1,59 @@ +/// +/// +/// + +declare namespace NodeJS { + interface ProcessEnv { + readonly NODE_ENV: 'development' | 'production' | 'test'; + readonly PUBLIC_URL: string; + } +} + +declare module '*.bmp' { + const src: string; + export default src; +} + +declare module '*.gif' { + const src: string; + export default src; +} + +declare module '*.jpg' { + const src: string; + export default src; +} + +declare module '*.jpeg' { + const src: string; + export default src; +} + +declare module '*.png' { + const src: string; + export default src; +} + +declare module '*.webp' { + const src: string; + export default src; +} + +declare module '*.svg' { + import * as React from 'react'; + + export const ReactComponent: React.FunctionComponent>; + + const src: string; + export default src; +} + +declare module '*.module.css' { + const classes: { readonly [key: string]: string }; + export default classes; +} + +declare module '*.module.less' { + const classes: { readonly [key: string]: string }; + export default classes; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3f571bb --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,32 @@ + +{ + "compilerOptions": { + "target": "esnext", + "module": "commonjs", + "jsx": "react", + "declaration": true, + "outDir": "lib", + "rootDir": ".", + "strict": true, /* Enable all strict type-checking options. */ + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "importHelpers": true, + "noImplicitAny": true, + "resolveJsonModule": true, + "sourceMap": true, + "baseUrl": "./src" + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "build", + "dist", + "**/*.spec.ts", + "**/*.test.ts" + ], + "typeRoots": [ + "./node_modules/@types" + ] +} \ No newline at end of file