Merge pull request #264 from wakatime/get-project-name-only-from-valid-url
Properly check if a url match is a project / repository
This commit is contained in:
52
package-lock.json
generated
52
package-lock.json
generated
@@ -17,6 +17,7 @@
|
|||||||
"idb": "^7.1.1",
|
"idb": "^7.1.1",
|
||||||
"jquery": "^3.6.3",
|
"jquery": "^3.6.3",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
|
"node-html-parser": "^6.1.13",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "^8.0.5",
|
||||||
@@ -6348,8 +6349,7 @@
|
|||||||
"node_modules/boolbase": {
|
"node_modules/boolbase": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/bootstrap": {
|
"node_modules/bootstrap": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
@@ -8043,7 +8043,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
||||||
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
|
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"boolbase": "^1.0.0",
|
"boolbase": "^1.0.0",
|
||||||
"css-what": "^6.1.0",
|
"css-what": "^6.1.0",
|
||||||
@@ -8059,7 +8058,6 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"domelementtype": "^2.3.0",
|
"domelementtype": "^2.3.0",
|
||||||
"domhandler": "^5.0.2",
|
"domhandler": "^5.0.2",
|
||||||
@@ -8073,7 +8071,6 @@
|
|||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@@ -8085,7 +8082,6 @@
|
|||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"domelementtype": "^2.3.0"
|
"domelementtype": "^2.3.0"
|
||||||
},
|
},
|
||||||
@@ -8100,7 +8096,6 @@
|
|||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
||||||
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dom-serializer": "^2.0.0",
|
"dom-serializer": "^2.0.0",
|
||||||
"domelementtype": "^2.3.0",
|
"domelementtype": "^2.3.0",
|
||||||
@@ -8114,7 +8109,6 @@
|
|||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12"
|
"node": ">=0.12"
|
||||||
},
|
},
|
||||||
@@ -8126,7 +8120,6 @@
|
|||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
||||||
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
|
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
},
|
},
|
||||||
@@ -11383,7 +11376,6 @@
|
|||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
||||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"he": "bin/he"
|
"he": "bin/he"
|
||||||
}
|
}
|
||||||
@@ -16769,6 +16761,16 @@
|
|||||||
"node": ">= 6.13.0"
|
"node": ">= 6.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-html-parser": {
|
||||||
|
"version": "6.1.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz",
|
||||||
|
"integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"css-select": "^5.1.0",
|
||||||
|
"he": "1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-int64": {
|
"node_modules/node-int64": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||||
@@ -16895,7 +16897,6 @@
|
|||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||||
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"boolbase": "^1.0.0"
|
"boolbase": "^1.0.0"
|
||||||
},
|
},
|
||||||
@@ -27257,8 +27258,7 @@
|
|||||||
"boolbase": {
|
"boolbase": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"bootstrap": {
|
"bootstrap": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
@@ -28574,7 +28574,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
||||||
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
|
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"boolbase": "^1.0.0",
|
"boolbase": "^1.0.0",
|
||||||
"css-what": "^6.1.0",
|
"css-what": "^6.1.0",
|
||||||
@@ -28587,7 +28586,6 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"domelementtype": "^2.3.0",
|
"domelementtype": "^2.3.0",
|
||||||
"domhandler": "^5.0.2",
|
"domhandler": "^5.0.2",
|
||||||
@@ -28597,14 +28595,12 @@
|
|||||||
"domelementtype": {
|
"domelementtype": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"domhandler": {
|
"domhandler": {
|
||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"domelementtype": "^2.3.0"
|
"domelementtype": "^2.3.0"
|
||||||
}
|
}
|
||||||
@@ -28613,7 +28609,6 @@
|
|||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
||||||
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"dom-serializer": "^2.0.0",
|
"dom-serializer": "^2.0.0",
|
||||||
"domelementtype": "^2.3.0",
|
"domelementtype": "^2.3.0",
|
||||||
@@ -28623,16 +28618,14 @@
|
|||||||
"entities": {
|
"entities": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"css-what": {
|
"css-what": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
||||||
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
|
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"css.escape": {
|
"css.escape": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
@@ -31102,8 +31095,7 @@
|
|||||||
"he": {
|
"he": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
||||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"hmac-drbg": {
|
"hmac-drbg": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -35120,6 +35112,15 @@
|
|||||||
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node-html-parser": {
|
||||||
|
"version": "6.1.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz",
|
||||||
|
"integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==",
|
||||||
|
"requires": {
|
||||||
|
"css-select": "^5.1.0",
|
||||||
|
"he": "1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node-int64": {
|
"node-int64": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||||
@@ -35223,7 +35224,6 @@
|
|||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||||
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"boolbase": "^1.0.0"
|
"boolbase": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
"idb": "^7.1.1",
|
"idb": "^7.1.1",
|
||||||
"jquery": "^3.6.3",
|
"jquery": "^3.6.3",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
|
"node-html-parser": "^6.1.13",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "^8.0.5",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import browser from 'webextension-polyfill';
|
import browser from 'webextension-polyfill';
|
||||||
import WakaTimeCore from './core/WakaTimeCore';
|
import WakaTimeCore from './core/WakaTimeCore';
|
||||||
import { PostHeartbeatMessage } from './types/heartbeats';
|
import { PostHeartbeatMessage } from './types/heartbeats';
|
||||||
|
import { getHtmlContentByTabId } from './utils';
|
||||||
|
|
||||||
// Add a listener to resolve alarms
|
// Add a listener to resolve alarms
|
||||||
browser.alarms.onAlarm.addListener(async (alarm) => {
|
browser.alarms.onAlarm.addListener(async (alarm) => {
|
||||||
@@ -22,9 +23,10 @@ browser.alarms.create('heartbeatAlarm', { periodInMinutes: 2 });
|
|||||||
/**
|
/**
|
||||||
* Whenever a active tab is changed it records a heartbeat with that tab url.
|
* Whenever a active tab is changed it records a heartbeat with that tab url.
|
||||||
*/
|
*/
|
||||||
browser.tabs.onActivated.addListener(async () => {
|
browser.tabs.onActivated.addListener(async (activeInfo) => {
|
||||||
console.log('recording a heartbeat - active tab changed');
|
console.log('recording a heartbeat - active tab changed');
|
||||||
await WakaTimeCore.recordHeartbeat();
|
const html = await getHtmlContentByTabId(activeInfo.tabId);
|
||||||
|
await WakaTimeCore.recordHeartbeat(html);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +35,17 @@ browser.tabs.onActivated.addListener(async () => {
|
|||||||
browser.windows.onFocusChanged.addListener(async (windowId) => {
|
browser.windows.onFocusChanged.addListener(async (windowId) => {
|
||||||
if (windowId != browser.windows.WINDOW_ID_NONE) {
|
if (windowId != browser.windows.WINDOW_ID_NONE) {
|
||||||
console.log('recording a heartbeat - active window changed');
|
console.log('recording a heartbeat - active window changed');
|
||||||
await WakaTimeCore.recordHeartbeat();
|
const tabs: browser.Tabs.Tab[] = await browser.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
let html = '';
|
||||||
|
const tabId = tabs[0]?.id;
|
||||||
|
if (tabId) {
|
||||||
|
html = await getHtmlContentByTabId(tabId);
|
||||||
|
}
|
||||||
|
await WakaTimeCore.recordHeartbeat(html);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -50,7 +62,8 @@ browser.tabs.onUpdated.addListener(async (tabId, changeInfo) => {
|
|||||||
});
|
});
|
||||||
// If tab updated is the same as active tab
|
// If tab updated is the same as active tab
|
||||||
if (tabId == tabs[0]?.id) {
|
if (tabId == tabs[0]?.id) {
|
||||||
await WakaTimeCore.recordHeartbeat();
|
const html = await getHtmlContentByTabId(tabId);
|
||||||
|
await WakaTimeCore.recordHeartbeat(html);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -63,9 +76,12 @@ self.addEventListener('activate', async () => {
|
|||||||
await WakaTimeCore.createDB();
|
await WakaTimeCore.createDB();
|
||||||
});
|
});
|
||||||
|
|
||||||
browser.runtime.onMessage.addListener(async (request: PostHeartbeatMessage) => {
|
browser.runtime.onMessage.addListener(async (request: PostHeartbeatMessage, sender) => {
|
||||||
if (request.recordHeartbeat === true) {
|
if (request.recordHeartbeat === true) {
|
||||||
await WakaTimeCore.recordHeartbeat(request.projectDetails);
|
if (sender.tab?.id) {
|
||||||
|
const html = await getHtmlContentByTabId(sender.tab.id);
|
||||||
|
await WakaTimeCore.recordHeartbeat(html, request.projectDetails);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ describe('MainList', () => {
|
|||||||
totalTimeLoggedToday = '1/1/1999';
|
totalTimeLoggedToday = '1/1/1999';
|
||||||
});
|
});
|
||||||
it('should render properly', () => {
|
it('should render properly', () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
const { container } = renderWithProviders(
|
const { container } = renderWithProviders(
|
||||||
<MainList loggingEnabled={loggingEnabled} totalTimeLoggedToday={totalTimeLoggedToday} />,
|
<MainList loggingEnabled={loggingEnabled} totalTimeLoggedToday={totalTimeLoggedToday} />,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ jest.mock('webextension-polyfill', () => {
|
|||||||
|
|
||||||
describe('NavBar', () => {
|
describe('NavBar', () => {
|
||||||
it('should render properly', () => {
|
it('should render properly', () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
const { container } = renderWithProviders(<NavBar />);
|
const { container } = renderWithProviders(<NavBar />);
|
||||||
expect(container).toMatchInlineSnapshot(`
|
expect(container).toMatchInlineSnapshot(`
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ class WakaTimeCore {
|
|||||||
* Depending on various factors detects the current active tab URL or domain,
|
* Depending on various factors detects the current active tab URL or domain,
|
||||||
* and sends it to WakaTime for logging.
|
* and sends it to WakaTime for logging.
|
||||||
*/
|
*/
|
||||||
async recordHeartbeat(payload: Record<string, unknown> = {}): Promise<void> {
|
async recordHeartbeat(html: string, payload: Record<string, unknown> = {}): Promise<void> {
|
||||||
const apiKey = await getApiKey();
|
const apiKey = await getApiKey();
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
return changeExtensionState('notLogging');
|
return changeExtensionState('notLogging');
|
||||||
@@ -164,7 +164,7 @@ class WakaTimeCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Checks dev websites
|
// Checks dev websites
|
||||||
const project = generateProjectFromDevSites(url);
|
const project = generateProjectFromDevSites(url, html);
|
||||||
|
|
||||||
// Check if code reviewing
|
// Check if code reviewing
|
||||||
const codeReviewing = isCodeReviewing(url);
|
const codeReviewing = isCodeReviewing(url);
|
||||||
|
|||||||
@@ -32,6 +32,6 @@
|
|||||||
"options_ui": {
|
"options_ui": {
|
||||||
"page": "options.html"
|
"page": "options.html"
|
||||||
},
|
},
|
||||||
"permissions": ["alarms", "tabs", "storage", "idle"],
|
"permissions": ["<all_urls>", "alarms", "tabs", "storage", "idle", "activeTab", "scripting"],
|
||||||
"version": "3.0.22"
|
"version": "3.0.22"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,6 @@
|
|||||||
"options_ui": {
|
"options_ui": {
|
||||||
"page": "options.html"
|
"page": "options.html"
|
||||||
},
|
},
|
||||||
"permissions": ["alarms", "tabs", "storage", "idle"],
|
"permissions": ["<all_urls>", "alarms", "tabs", "storage", "idle", "activeTab", "scripting"],
|
||||||
"version": "3.0.22"
|
"version": "3.0.22"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,6 @@
|
|||||||
"chrome_style": false,
|
"chrome_style": false,
|
||||||
"page": "options.html"
|
"page": "options.html"
|
||||||
},
|
},
|
||||||
"permissions": ["<all_urls>", "alarms", "tabs", "storage", "idle"],
|
"permissions": ["<all_urls>", "alarms", "tabs", "storage", "idle", "activeTab", "scripting"],
|
||||||
"version": "3.0.22"
|
"version": "3.0.22"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,14 @@ import { createRoot } from 'react-dom/client';
|
|||||||
import Options from './components/Options';
|
import Options from './components/Options';
|
||||||
|
|
||||||
/* This is a fix for Bootstrap requiring jQuery */
|
/* This is a fix for Bootstrap requiring jQuery */
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-expect-error
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
global.jQuery = require('jquery');
|
global.jQuery = require('jquery');
|
||||||
require('bootstrap');
|
require('bootstrap');
|
||||||
|
|
||||||
const container = document.getElementById('wakatime-options');
|
const container = document.getElementById('wakatime-options');
|
||||||
const root = createRoot(container!);
|
if (container) {
|
||||||
|
const root = createRoot(container);
|
||||||
root.render(<Options />);
|
root.render(<Options />);
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,12 +8,14 @@ import checkCurrentUser from './utils/checkCurrentUser';
|
|||||||
import 'bootstrap/dist/js/bootstrap';
|
import 'bootstrap/dist/js/bootstrap';
|
||||||
|
|
||||||
const container = document.getElementById('wakatime');
|
const container = document.getElementById('wakatime');
|
||||||
const root = createRoot(container!);
|
if (container) {
|
||||||
const store = createStore('WakaTime-Options');
|
const root = createRoot(container);
|
||||||
checkCurrentUser(store)(30 * 1000);
|
const store = createStore();
|
||||||
|
checkCurrentUser(store)(30 * 1000);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<WakaTime />
|
<WakaTime />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export interface SendHeartbeat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ProjectDetails {
|
export interface ProjectDetails {
|
||||||
|
[key: string]: string;
|
||||||
category: string;
|
category: string;
|
||||||
editor: string;
|
editor: string;
|
||||||
language: string;
|
language: string;
|
||||||
|
|||||||
@@ -1,33 +1,146 @@
|
|||||||
|
import { parse } from 'node-html-parser';
|
||||||
|
|
||||||
export const IS_EDGE = navigator.userAgent.includes('Edg');
|
export const IS_EDGE = navigator.userAgent.includes('Edg');
|
||||||
export const IS_FIREFOX = navigator.userAgent.includes('Firefox');
|
export const IS_FIREFOX = navigator.userAgent.includes('Firefox');
|
||||||
export const IS_CHROME = IS_EDGE === false && IS_FIREFOX === false;
|
export const IS_CHROME = IS_EDGE === false && IS_FIREFOX === false;
|
||||||
|
|
||||||
const REG_LIST = [
|
type ProjectNameExtractor = (url: string, html: string) => string | null;
|
||||||
// GitHub. Eg. URL: https://github.com/workspace-name/project-name
|
|
||||||
/(?<=github\.(?:com|dev)\/[^/]+\/)([^/?#]+)/,
|
const GitHub: ProjectNameExtractor = (url: string, html: string): string | null => {
|
||||||
// Gitlab. Eg. URL: https://gitlab.com/workspace-name/project-name
|
const { hostname } = new URL(url);
|
||||||
/(?<=gitlab\.com\/[^/]+\/)([^/?#]+)/,
|
const match = url.match(/(?<=github\.(?:com|dev)\/[^/]+\/)([^/?#]+)/);
|
||||||
// BitBucket. Eg. URL: https://bitbucket.org/workspace-name/project-name/src
|
|
||||||
/(?<=bitbucket\.org\/[^/]+\/)([^/?#]+)/,
|
if (match) {
|
||||||
// Travis CI. Eg. URL: https://app.travis-ci.com/github/workspace-name/project-name/no-build?serverType=git
|
if (hostname.endsWith('.com')) {
|
||||||
/(?<=app\.travis-ci\.com\/[^/]+\/[^/]+\/)([^/?#]+)/,
|
const root = parse(html);
|
||||||
// Circle CI. Eg. URL: https://app.circleci.com/projects/project-setup/github/workspace-name/project-name/
|
const repoName = root
|
||||||
|
.querySelector('meta[name=octolytics-dimension-repository_nwo]')
|
||||||
|
?.getAttribute('content');
|
||||||
|
if (!repoName || repoName.split('/')[1] !== match[0]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const GitLab: ProjectNameExtractor = (url: string, html: string): string | null => {
|
||||||
|
const match = url.match(/(?<=gitlab\.com\/[^/]+\/)([^/?#]+)/);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const root = parse(html);
|
||||||
|
const repoName = root.querySelector('body')?.getAttribute('data-project-full-path');
|
||||||
|
if (!repoName || repoName.split('/')[1] !== match[0]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return match[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const BitBucket: ProjectNameExtractor = (url: string, html: string): string | null => {
|
||||||
|
const match = url.match(/(?<=bitbucket\.org\/[^/]+\/)([^/?#]+)/);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const root = parse(html);
|
||||||
|
// this regex extracts the project name from the title
|
||||||
|
// eg. title: jhondoe / my-test-repo — Bitbucket
|
||||||
|
const match2 = root.querySelector('title')?.textContent.match(/(?<=\/\s)([^/\s]+)(?=\s—)/);
|
||||||
|
if (match2 && match2[0] === match[0]) {
|
||||||
|
return match[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const TravisCI: ProjectNameExtractor = (url: string, html: string): string | null => {
|
||||||
|
const match = url.match(/(?<=app\.travis-ci\.com\/[^/]+\/[^/]+\/)([^/?#]+)/);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const root = parse(html);
|
||||||
|
const projectName = root.querySelector('#ember737')?.textContent;
|
||||||
|
if (projectName === match[0]) {
|
||||||
|
return match[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CircleCI: ProjectNameExtractor = (url: string, html: string): string | null => {
|
||||||
|
const projectPageMatch = url.match(
|
||||||
/(?<=app\.circleci\.com\/projects\/[^/]+\/[^/]+\/[^/]+\/)([^/?#]+)/,
|
/(?<=app\.circleci\.com\/projects\/[^/]+\/[^/]+\/[^/]+\/)([^/?#]+)/,
|
||||||
// Vercel. Eg. URL: http://vercel.com/team-name/project-name
|
);
|
||||||
/(?<=vercel\.com\/[^/]+\/)([^/?#]+)/,
|
|
||||||
|
if (projectPageMatch) {
|
||||||
|
const root = parse(html);
|
||||||
|
const seconndBreadcrumbLabel = root.querySelector(
|
||||||
|
'#__next > div:nth-child(2) > div > div > main > div > header > div:nth-child(1) > ol > li:nth-child(2) > div > div > span',
|
||||||
|
)?.textContent;
|
||||||
|
const seconndBreadcrumbValue = root.querySelector(
|
||||||
|
'#__next > div:nth-child(2) > div > div > main > div > header > div:nth-child(1) > ol > li:nth-child(2) > div > span',
|
||||||
|
)?.textContent;
|
||||||
|
if (seconndBreadcrumbLabel === 'Project' && seconndBreadcrumbValue === projectPageMatch[0]) {
|
||||||
|
return projectPageMatch[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const settingsPageMatch = url.match(
|
||||||
|
/(?<=app\.circleci\.com\/settings\/project\/[^/]+\/[^/]+\/)([^/?#]+)/,
|
||||||
|
);
|
||||||
|
if (settingsPageMatch) {
|
||||||
|
const root = parse(html);
|
||||||
|
const pageTitle = root.querySelector(
|
||||||
|
'#__next > div > div:nth-child(1) > header > div > div:nth-child(2) > h1',
|
||||||
|
)?.textContent;
|
||||||
|
const pageSubtitle = root.querySelector(
|
||||||
|
'#__next > div > div:nth-child(1) > header > div > div:nth-child(2) > div',
|
||||||
|
)?.textContent;
|
||||||
|
if (pageTitle === 'Project Settings' && pageSubtitle === settingsPageMatch[0]) {
|
||||||
|
return settingsPageMatch[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Vercel: ProjectNameExtractor = (url: string, html: string): string | null => {
|
||||||
|
const match = url.match(/(?<=vercel\.com\/[^/]+\/)([^/?#]+)/);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const root = parse(html);
|
||||||
|
// this regex extracts the project name from the title
|
||||||
|
// eg. title: test-website - Overview – Vercel
|
||||||
|
const match2 = root.querySelector('title')?.textContent.match(/^[^\s]+(?=\s-\s)/);
|
||||||
|
if (match2 && match2[0] === match[0]) {
|
||||||
|
return match[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProjectNameExtractors: ProjectNameExtractor[] = [
|
||||||
|
GitHub,
|
||||||
|
GitLab,
|
||||||
|
BitBucket,
|
||||||
|
TravisCI,
|
||||||
|
CircleCI,
|
||||||
|
Vercel,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const generateProjectFromDevSites = (url: string): string | null => {
|
export const generateProjectFromDevSites = (url: string, html: string): string | null => {
|
||||||
let match: RegExpMatchArray | null = null;
|
for (const projectNameExtractor of ProjectNameExtractors) {
|
||||||
|
const projectName = projectNameExtractor(url, html);
|
||||||
for (const reg of REG_LIST) {
|
if (projectName) {
|
||||||
match = url.match(reg);
|
return projectName;
|
||||||
if (match) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
return match?.[0] ?? null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const CODE_REVIEW_URL_REG_LIST = [/github.com\/[^/]+\/[^/]+\/pull\/\d+\/files/];
|
const CODE_REVIEW_URL_REG_LIST = [/github.com\/[^/]+\/[^/]+\/pull\/\d+\/files/];
|
||||||
@@ -40,3 +153,10 @@ export const isCodeReviewing = (url: string): boolean => {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getHtmlContentByTabId = async (tabId: number): Promise<string> => {
|
||||||
|
const response = (await browser.tabs.sendMessage(tabId, { message: 'get_html' })) as {
|
||||||
|
html: string;
|
||||||
|
};
|
||||||
|
return response.html;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import React, { PropsWithChildren } from 'react';
|
|
||||||
import { render } from '@testing-library/react';
|
|
||||||
import type { RenderOptions } from '@testing-library/react';
|
|
||||||
import { combineReducers, configureStore, Store } from '@reduxjs/toolkit';
|
|
||||||
import type { PreloadedState } from '@reduxjs/toolkit';
|
import type { PreloadedState } from '@reduxjs/toolkit';
|
||||||
|
import { combineReducers, configureStore, Store } from '@reduxjs/toolkit';
|
||||||
|
import type { RenderOptions } from '@testing-library/react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import React, { PropsWithChildren } from 'react';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { RootState } from '../stores/createStore';
|
import { RootState } from '../stores/createStore';
|
||||||
|
|
||||||
// As a basic setup, import your same slice reducers
|
// As a basic setup, import your same slice reducers
|
||||||
import userReducer, { initialState as InitalCurrentUser } from '../reducers/currentUser';
|
|
||||||
import configReducer, { initialConfigState } from '../reducers/configReducer';
|
import configReducer, { initialConfigState } from '../reducers/configReducer';
|
||||||
|
import userReducer, { initialState as InitalCurrentUser } from '../reducers/currentUser';
|
||||||
|
|
||||||
// This type interface extends the default options for render from RTL, as well
|
// This type interface extends the default options for render from RTL, as well
|
||||||
// as allows the user to specify other things such as initialState, store.
|
// as allows the user to specify other things such as initialState, store.
|
||||||
@@ -33,6 +33,7 @@ export function renderWithProviders(
|
|||||||
store = configureStore({ preloadedState, reducer: rootReducer }),
|
store = configureStore({ preloadedState, reducer: rootReducer }),
|
||||||
...renderOptions
|
...renderOptions
|
||||||
}: ExtendedRenderOptions = {},
|
}: ExtendedRenderOptions = {},
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
): any {
|
): any {
|
||||||
function Wrapper({ children }: PropsWithChildren<Record<string, unknown>>): JSX.Element {
|
function Wrapper({ children }: PropsWithChildren<Record<string, unknown>>): JSX.Element {
|
||||||
return <Provider store={store}>{children}</Provider>;
|
return <Provider store={store}>{children}</Provider>;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { AnyAction, Dispatch } from '@reduxjs/toolkit';
|
import { AnyAction, Dispatch } from '@reduxjs/toolkit';
|
||||||
import { setApiKey, setLoggingEnabled, setTotalTimeLoggedToday } from '../reducers/configReducer';
|
|
||||||
import config from '../config/config';
|
import config from '../config/config';
|
||||||
import WakaTimeCore from '../core/WakaTimeCore';
|
import WakaTimeCore from '../core/WakaTimeCore';
|
||||||
|
import { setApiKey, setLoggingEnabled, setTotalTimeLoggedToday } from '../reducers/configReducer';
|
||||||
import { setUser } from '../reducers/currentUser';
|
import { setUser } from '../reducers/currentUser';
|
||||||
|
import { getHtmlContentByTabId } from '.';
|
||||||
import changeExtensionState from './changeExtensionState';
|
import changeExtensionState from './changeExtensionState';
|
||||||
|
|
||||||
export const logUserIn = async (apiKey: string): Promise<void> => {
|
export const logUserIn = async (apiKey: string): Promise<void> => {
|
||||||
@@ -65,7 +66,17 @@ export const fetchUserData = async (
|
|||||||
dispatch(setLoggingEnabled(items.loggingEnabled as boolean));
|
dispatch(setLoggingEnabled(items.loggingEnabled as boolean));
|
||||||
dispatch(setTotalTimeLoggedToday(totalTimeLoggedTodayResponse.text));
|
dispatch(setTotalTimeLoggedToday(totalTimeLoggedTodayResponse.text));
|
||||||
|
|
||||||
await WakaTimeCore.recordHeartbeat();
|
const tabs = await browser.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true,
|
||||||
|
});
|
||||||
|
let html = '';
|
||||||
|
const tabId = tabs[0]?.id;
|
||||||
|
if (tabId) {
|
||||||
|
html = await getHtmlContentByTabId(tabId);
|
||||||
|
}
|
||||||
|
|
||||||
|
await WakaTimeCore.recordHeartbeat(html);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
await changeExtensionState('notSignedIn');
|
await changeExtensionState('notSignedIn');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,3 +83,9 @@ document.body.addEventListener(
|
|||||||
debounce(() => init()),
|
debounce(() => init()),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((request: { message: string }, sender, sendResponse) => {
|
||||||
|
if (request.message === 'get_html') {
|
||||||
|
sendResponse({ html: document.documentElement.outerHTML });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"outDir": "lib",
|
"outDir": "lib",
|
||||||
"lib": ["es2015", "es2016", "es2017", "dom"],
|
"lib": ["es2015", "es2016", "es2017", "dom"],
|
||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
"paths": {}
|
"paths": {},
|
||||||
|
"strictNullChecks": true
|
||||||
},
|
},
|
||||||
"exclude": []
|
"exclude": []
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user