init
This commit is contained in:
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
13
index.html
Normal file
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0"
|
||||
/>
|
||||
<title>jop</title>
|
||||
<!-- /index.html 必须存在, 否则 vite 无法注入 hmr 代码, plugin-monkey 以及其他插件 也无法注入相关辅助代码 -->
|
||||
<!-- /index.html must exist, if not, vite will not inject hmr code, plugin-monkey and others will not inject theirs related auxiliary code -->
|
||||
</head>
|
||||
</html>
|
||||
15
package.json
Normal file
15
package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "userjs-jop",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.8.4",
|
||||
"vite": "^3.1.4",
|
||||
"vite-plugin-monkey": "^2.5.1"
|
||||
}
|
||||
}
|
||||
537
pnpm-lock.yaml
generated
Normal file
537
pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1,537 @@
|
||||
lockfileVersion: 5.4
|
||||
|
||||
specifiers:
|
||||
typescript: ^4.8.4
|
||||
vite: ^3.1.4
|
||||
vite-plugin-monkey: ^2.5.1
|
||||
|
||||
devDependencies:
|
||||
typescript: 4.8.4
|
||||
vite: 3.1.4
|
||||
vite-plugin-monkey: 2.5.1_vite@3.1.4
|
||||
|
||||
packages:
|
||||
|
||||
/@esbuild/android-arm/0.15.10:
|
||||
resolution: {integrity: sha512-FNONeQPy/ox+5NBkcSbYJxoXj9GWu8gVGJTVmUyoOCKQFDTrHVKgNSzChdNt0I8Aj/iKcsDf2r9BFwv+FSNUXg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-loong64/0.15.10:
|
||||
resolution: {integrity: sha512-w0Ou3Z83LOYEkwaui2M8VwIp+nLi/NA60lBLMvaJ+vXVMcsARYdEzLNE7RSm4+lSg4zq4d7fAVuzk7PNQ5JFgg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/address/1.2.1:
|
||||
resolution: {integrity: sha512-B+6bi5D34+fDYENiH5qOlA0cV2rAGKuWZ9LeyUUehbXy8e0VS9e498yO0Jeeh+iM+6KbfudHTFjXw2MmJD4QRA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
dev: true
|
||||
|
||||
/cross-spawn/7.0.3:
|
||||
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
shebang-command: 2.0.0
|
||||
which: 2.0.2
|
||||
dev: true
|
||||
|
||||
/debug/2.6.9:
|
||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
dependencies:
|
||||
ms: 2.0.0
|
||||
dev: true
|
||||
|
||||
/define-lazy-prop/2.0.0:
|
||||
resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/detect-port/1.3.0:
|
||||
resolution: {integrity: sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==}
|
||||
engines: {node: '>= 4.2.1'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
address: 1.2.1
|
||||
debug: 2.6.9
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/dom-serializer/2.0.0:
|
||||
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
domhandler: 5.0.3
|
||||
entities: 4.4.0
|
||||
dev: true
|
||||
|
||||
/domelementtype/2.3.0:
|
||||
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
|
||||
dev: true
|
||||
|
||||
/domhandler/5.0.3:
|
||||
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
|
||||
engines: {node: '>= 4'}
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
dev: true
|
||||
|
||||
/domutils/3.0.1:
|
||||
resolution: {integrity: sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==}
|
||||
dependencies:
|
||||
dom-serializer: 2.0.0
|
||||
domelementtype: 2.3.0
|
||||
domhandler: 5.0.3
|
||||
dev: true
|
||||
|
||||
/entities/4.4.0:
|
||||
resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==}
|
||||
engines: {node: '>=0.12'}
|
||||
dev: true
|
||||
|
||||
/esbuild-android-64/0.15.10:
|
||||
resolution: {integrity: sha512-UI7krF8OYO1N7JYTgLT9ML5j4+45ra3amLZKx7LO3lmLt1Ibn8t3aZbX5Pu4BjWiqDuJ3m/hsvhPhK/5Y/YpnA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-android-arm64/0.15.10:
|
||||
resolution: {integrity: sha512-EOt55D6xBk5O05AK8brXUbZmoFj4chM8u3riGflLa6ziEoVvNjRdD7Cnp82NHQGfSHgYR06XsPI8/sMuA/cUwg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-darwin-64/0.15.10:
|
||||
resolution: {integrity: sha512-hbDJugTicqIm+WKZgp208d7FcXcaK8j2c0l+fqSJ3d2AzQAfjEYDRM3Z2oMeqSJ9uFxyj/muSACLdix7oTstRA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-darwin-arm64/0.15.10:
|
||||
resolution: {integrity: sha512-M1t5+Kj4IgSbYmunf2BB6EKLkWUq+XlqaFRiGOk8bmBapu9bCDrxjf4kUnWn59Dka3I27EiuHBKd1rSO4osLFQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-freebsd-64/0.15.10:
|
||||
resolution: {integrity: sha512-KMBFMa7C8oc97nqDdoZwtDBX7gfpolkk6Bcmj6YFMrtCMVgoU/x2DI1p74DmYl7CSS6Ppa3xgemrLrr5IjIn0w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-freebsd-arm64/0.15.10:
|
||||
resolution: {integrity: sha512-m2KNbuCX13yQqLlbSojFMHpewbn8wW5uDS6DxRpmaZKzyq8Dbsku6hHvh2U+BcLwWY4mpgXzFUoENEf7IcioGg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-32/0.15.10:
|
||||
resolution: {integrity: sha512-guXrwSYFAvNkuQ39FNeV4sNkNms1bLlA5vF1H0cazZBOLdLFIny6BhT+TUbK/hdByMQhtWQ5jI9VAmPKbVPu1w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-64/0.15.10:
|
||||
resolution: {integrity: sha512-jd8XfaSJeucMpD63YNMO1JCrdJhckHWcMv6O233bL4l6ogQKQOxBYSRP/XLWP+6kVTu0obXovuckJDcA0DKtQA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-arm/0.15.10:
|
||||
resolution: {integrity: sha512-6N8vThLL/Lysy9y4Ex8XoLQAlbZKUyExCWyayGi2KgTBelKpPgj6RZnUaKri0dHNPGgReJriKVU6+KDGQwn10A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-arm64/0.15.10:
|
||||
resolution: {integrity: sha512-GByBi4fgkvZFTHFDYNftu1DQ1GzR23jws0oWyCfhnI7eMOe+wgwWrc78dbNk709Ivdr/evefm2PJiUBMiusS1A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-mips64le/0.15.10:
|
||||
resolution: {integrity: sha512-BxP+LbaGVGIdQNJUNF7qpYjEGWb0YyHVSKqYKrn+pTwH/SiHUxFyJYSP3pqkku61olQiSBnSmWZ+YUpj78Tw7Q==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-ppc64le/0.15.10:
|
||||
resolution: {integrity: sha512-LoSQCd6498PmninNgqd/BR7z3Bsk/mabImBWuQ4wQgmQEeanzWd5BQU2aNi9mBURCLgyheuZS6Xhrw5luw3OkQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-riscv64/0.15.10:
|
||||
resolution: {integrity: sha512-Lrl9Cr2YROvPV4wmZ1/g48httE8z/5SCiXIyebiB5N8VT7pX3t6meI7TQVHw/wQpqP/AF4SksDuFImPTM7Z32Q==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-s390x/0.15.10:
|
||||
resolution: {integrity: sha512-ReP+6q3eLVVP2lpRrvl5EodKX7EZ1bS1/z5j6hsluAlZP5aHhk6ghT6Cq3IANvvDdscMMCB4QEbI+AjtvoOFpA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-netbsd-64/0.15.10:
|
||||
resolution: {integrity: sha512-iGDYtJCMCqldMskQ4eIV+QSS/CuT7xyy9i2/FjpKvxAuCzrESZXiA1L64YNj6/afuzfBe9i8m/uDkFHy257hTw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-openbsd-64/0.15.10:
|
||||
resolution: {integrity: sha512-ftMMIwHWrnrYnvuJQRJs/Smlcb28F9ICGde/P3FUTCgDDM0N7WA0o9uOR38f5Xe2/OhNCgkjNeb7QeaE3cyWkQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-sunos-64/0.15.10:
|
||||
resolution: {integrity: sha512-mf7hBL9Uo2gcy2r3rUFMjVpTaGpFJJE5QTDDqUFf1632FxteYANffDZmKbqX0PfeQ2XjUDE604IcE7OJeoHiyg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-windows-32/0.15.10:
|
||||
resolution: {integrity: sha512-ttFVo+Cg8b5+qHmZHbEc8Vl17kCleHhLzgT8X04y8zudEApo0PxPg9Mz8Z2cKH1bCYlve1XL8LkyXGFjtUYeGg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-windows-64/0.15.10:
|
||||
resolution: {integrity: sha512-2H0gdsyHi5x+8lbng3hLbxDWR7mKHWh5BXZGKVG830KUmXOOWFE2YKJ4tHRkejRduOGDrBvHBriYsGtmTv3ntA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild-windows-arm64/0.15.10:
|
||||
resolution: {integrity: sha512-S+th4F+F8VLsHLR0zrUcG+Et4hx0RKgK1eyHc08kztmLOES8BWwMiaGdoW9hiXuzznXQ0I/Fg904MNbr11Nktw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/esbuild/0.15.10:
|
||||
resolution: {integrity: sha512-N7wBhfJ/E5fzn/SpNgX+oW2RLRjwaL8Y0ezqNqhjD6w0H2p0rDuEz2FKZqpqLnO8DCaWumKe8dsC/ljvVSSxng==}
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
optionalDependencies:
|
||||
'@esbuild/android-arm': 0.15.10
|
||||
'@esbuild/linux-loong64': 0.15.10
|
||||
esbuild-android-64: 0.15.10
|
||||
esbuild-android-arm64: 0.15.10
|
||||
esbuild-darwin-64: 0.15.10
|
||||
esbuild-darwin-arm64: 0.15.10
|
||||
esbuild-freebsd-64: 0.15.10
|
||||
esbuild-freebsd-arm64: 0.15.10
|
||||
esbuild-linux-32: 0.15.10
|
||||
esbuild-linux-64: 0.15.10
|
||||
esbuild-linux-arm: 0.15.10
|
||||
esbuild-linux-arm64: 0.15.10
|
||||
esbuild-linux-mips64le: 0.15.10
|
||||
esbuild-linux-ppc64le: 0.15.10
|
||||
esbuild-linux-riscv64: 0.15.10
|
||||
esbuild-linux-s390x: 0.15.10
|
||||
esbuild-netbsd-64: 0.15.10
|
||||
esbuild-openbsd-64: 0.15.10
|
||||
esbuild-sunos-64: 0.15.10
|
||||
esbuild-windows-32: 0.15.10
|
||||
esbuild-windows-64: 0.15.10
|
||||
esbuild-windows-arm64: 0.15.10
|
||||
dev: true
|
||||
|
||||
/fsevents/2.3.2:
|
||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/function-bind/1.1.1:
|
||||
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
|
||||
dev: true
|
||||
|
||||
/has/1.0.3:
|
||||
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
dependencies:
|
||||
function-bind: 1.1.1
|
||||
dev: true
|
||||
|
||||
/htmlparser2/8.0.1:
|
||||
resolution: {integrity: sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==}
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
domhandler: 5.0.3
|
||||
domutils: 3.0.1
|
||||
entities: 4.4.0
|
||||
dev: true
|
||||
|
||||
/is-core-module/2.10.0:
|
||||
resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==}
|
||||
dependencies:
|
||||
has: 1.0.3
|
||||
dev: true
|
||||
|
||||
/is-docker/2.2.1:
|
||||
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/is-wsl/2.2.0:
|
||||
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
is-docker: 2.2.1
|
||||
dev: true
|
||||
|
||||
/isexe/2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
dev: true
|
||||
|
||||
/mrmime/1.0.1:
|
||||
resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/ms/2.0.0:
|
||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||
dev: true
|
||||
|
||||
/nanoid/3.3.4:
|
||||
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/node-fetch/2.6.7:
|
||||
resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==}
|
||||
engines: {node: 4.x || >=6.0.0}
|
||||
peerDependencies:
|
||||
encoding: ^0.1.0
|
||||
peerDependenciesMeta:
|
||||
encoding:
|
||||
optional: true
|
||||
dependencies:
|
||||
whatwg-url: 5.0.0
|
||||
dev: true
|
||||
|
||||
/open/8.4.0:
|
||||
resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
define-lazy-prop: 2.0.0
|
||||
is-docker: 2.2.1
|
||||
is-wsl: 2.2.0
|
||||
dev: true
|
||||
|
||||
/path-key/3.1.1:
|
||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/path-parse/1.0.7:
|
||||
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
||||
dev: true
|
||||
|
||||
/picocolors/1.0.0:
|
||||
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
||||
dev: true
|
||||
|
||||
/postcss/8.4.17:
|
||||
resolution: {integrity: sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
dependencies:
|
||||
nanoid: 3.3.4
|
||||
picocolors: 1.0.0
|
||||
source-map-js: 1.0.2
|
||||
dev: true
|
||||
|
||||
/resolve/1.22.1:
|
||||
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
is-core-module: 2.10.0
|
||||
path-parse: 1.0.7
|
||||
supports-preserve-symlinks-flag: 1.0.0
|
||||
dev: true
|
||||
|
||||
/rollup/2.78.1:
|
||||
resolution: {integrity: sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
hasBin: true
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: true
|
||||
|
||||
/shebang-command/2.0.0:
|
||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
shebang-regex: 3.0.0
|
||||
dev: true
|
||||
|
||||
/shebang-regex/3.0.0:
|
||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/source-map-js/1.0.2:
|
||||
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/supports-preserve-symlinks-flag/1.0.0:
|
||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: true
|
||||
|
||||
/tr46/0.0.3:
|
||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||
dev: true
|
||||
|
||||
/typescript/4.8.4:
|
||||
resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==}
|
||||
engines: {node: '>=4.2.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/vite-plugin-monkey/2.5.1_vite@3.1.4:
|
||||
resolution: {integrity: sha512-18eKt5++5eRF7rn2nXm7GjHECxSvBh36OiYnYR2vpRYIw+052fEAg7XvAAGCY1H3jb+1ox6ZOkmMvTPNubRaQg==}
|
||||
engines: {node: ^14.18 || >= 16, pnpm: '>=6'}
|
||||
peerDependencies:
|
||||
vite: ^2.0.0 || ^3.0.0
|
||||
dependencies:
|
||||
cross-spawn: 7.0.3
|
||||
detect-port: 1.3.0
|
||||
htmlparser2: 8.0.1
|
||||
mrmime: 1.0.1
|
||||
node-fetch: 2.6.7
|
||||
open: 8.4.0
|
||||
picocolors: 1.0.0
|
||||
vite: 3.1.4
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/vite/3.1.4:
|
||||
resolution: {integrity: sha512-JoQI08aBjY9lycL7jcEq4p9o1xUjq5aRvdH4KWaXtkSx7e7RpAh9D3IjzDWRD4Fg44LS3oDAIOG/Kq1L+82psA==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
less: '*'
|
||||
sass: '*'
|
||||
stylus: '*'
|
||||
terser: ^5.4.0
|
||||
peerDependenciesMeta:
|
||||
less:
|
||||
optional: true
|
||||
sass:
|
||||
optional: true
|
||||
stylus:
|
||||
optional: true
|
||||
terser:
|
||||
optional: true
|
||||
dependencies:
|
||||
esbuild: 0.15.10
|
||||
postcss: 8.4.17
|
||||
resolve: 1.22.1
|
||||
rollup: 2.78.1
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: true
|
||||
|
||||
/webidl-conversions/3.0.1:
|
||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||
dev: true
|
||||
|
||||
/whatwg-url/5.0.0:
|
||||
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||
dependencies:
|
||||
tr46: 0.0.3
|
||||
webidl-conversions: 3.0.1
|
||||
dev: true
|
||||
|
||||
/which/2.0.2:
|
||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||
engines: {node: '>= 8'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
dev: true
|
||||
48
src/createNode.ts
Normal file
48
src/createNode.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
export function createPanel() {
|
||||
const parentNode = document.querySelector("body");
|
||||
const panelNode = document.createElement("div");
|
||||
parentNode && parentNode.appendChild(panelNode);
|
||||
panelNode.classList.add("jop-panel");
|
||||
panelNode.addEventListener("click", () => {
|
||||
const class1 = panelNode.classList[1];
|
||||
if (class1 === undefined) {
|
||||
panelNode.classList.add("jop-panel_open");
|
||||
} else {
|
||||
panelNode.classList.remove("jop-panel_open");
|
||||
}
|
||||
});
|
||||
|
||||
return panelNode;
|
||||
}
|
||||
|
||||
export function createButtonNode(panelNode: HTMLDivElement, siteName: string, siteUrl: string) {
|
||||
const button = document.createElement("a");
|
||||
button.setAttribute("target", "_blank");
|
||||
button.classList.add("jop-button");
|
||||
button.innerHTML = siteName;
|
||||
/** 先给上默认链接 */
|
||||
button.href = siteUrl;
|
||||
button.addEventListener("click", (e) => e.stopPropagation());
|
||||
panelNode.appendChild(button);
|
||||
|
||||
/** 加载动画 */
|
||||
const loadAni = document.createElement("span");
|
||||
loadAni.classList.add("jop-button-loading");
|
||||
button.appendChild(loadAni);
|
||||
|
||||
/** 设置按钮状态样式 */ const setButtonStatus = (
|
||||
targetLink: string,
|
||||
color: "red" | "green",
|
||||
hasLeakage = false,
|
||||
hasSubtitle = false,
|
||||
) => {
|
||||
button.href = targetLink;
|
||||
|
||||
button.classList.add(`jop-button_${color}`);
|
||||
loadAni.classList.remove("jop-button-loading");
|
||||
hasLeakage && button.classList.add("jop-button_leakage");
|
||||
hasSubtitle && button.classList.add("jop-button_subtitle");
|
||||
};
|
||||
|
||||
return { button, setButtonStatus };
|
||||
}
|
||||
42
src/index.ts
Normal file
42
src/index.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { createButtonNode, createPanel } from "./createNode";
|
||||
import { matchList } from "./matchList";
|
||||
import { siteList } from "./siteList";
|
||||
import { xhr } from "./xhr";
|
||||
|
||||
import type { Cms } from "./matchList";
|
||||
|
||||
import "./style.css";
|
||||
|
||||
function getCode(cmsName: Cms["name"]) {
|
||||
if (cmsName === "javdb") {
|
||||
return document.querySelector<HTMLElement>(`[data-clipboard-text]`)?.dataset
|
||||
.clipboardText as string;
|
||||
} else if (cmsName === "javbus") {
|
||||
return document
|
||||
.querySelector<HTMLElement>(`span[style="color:#CC0000;"]`)
|
||||
?.innerText.replace("复制", "") as string;
|
||||
} else {
|
||||
return document.querySelector<HTMLElement>(`#video_id td.text`)?.innerHTML as string;
|
||||
}
|
||||
}
|
||||
|
||||
export async function main(HOSTNAME: string) {
|
||||
/** 当前 macth 站点对象 */
|
||||
const cms = matchList.find((item) => item.hostname === HOSTNAME) as Cms;
|
||||
const CODE = getCode(cms.name);
|
||||
const panel = createPanel();
|
||||
|
||||
/** 禁用部分 */
|
||||
const envSiteList = siteList.filter((item) => item.disable !== cms.name);
|
||||
envSiteList.forEach(async (siteItem) => {
|
||||
const siteUrl = siteItem.url.replace("{{code}}", CODE);
|
||||
|
||||
const { setButtonStatus } = createButtonNode(panel, siteItem.name, siteUrl);
|
||||
|
||||
const { isSuccess, hasLeakage, hasSubtitle, targetLink } = await xhr(siteItem, siteUrl, CODE);
|
||||
|
||||
setButtonStatus(targetLink, isSuccess ? "green" : "red", hasLeakage, hasSubtitle);
|
||||
});
|
||||
}
|
||||
|
||||
main(window.location.hostname);
|
||||
26
src/matchList.ts
Normal file
26
src/matchList.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export type Cms = {
|
||||
name: string;
|
||||
enable: boolean;
|
||||
hostname: string;
|
||||
panelParentQueryStr: string;
|
||||
};
|
||||
export const matchList: Cms[] = [
|
||||
{
|
||||
name: "javdb",
|
||||
enable: true,
|
||||
hostname: "javdb.com",
|
||||
panelParentQueryStr: "video-meta-panel",
|
||||
},
|
||||
{
|
||||
name: "javbus",
|
||||
enable: true,
|
||||
hostname: "www.javbus.com",
|
||||
panelParentQueryStr: "div.row.movie",
|
||||
},
|
||||
{
|
||||
name: "javlib",
|
||||
enable: true,
|
||||
hostname: "www.javlibrary.com",
|
||||
panelParentQueryStr: "#video_jacket_info",
|
||||
},
|
||||
];
|
||||
200
src/siteList.ts
Normal file
200
src/siteList.ts
Normal file
@@ -0,0 +1,200 @@
|
||||
export interface DomQuery_parser {
|
||||
/** 部分网站搜索页结果第一个是广告,所以要加一个 index */
|
||||
listIndex?: number;
|
||||
/** code 是用空格分割的 */
|
||||
spaceCode?: boolean;
|
||||
linkQuery: string;
|
||||
titleQuery: string;
|
||||
/** 确定返回颜色,暂未启用 */
|
||||
certainColor?: string;
|
||||
}
|
||||
|
||||
export interface DomQuery_get {
|
||||
/** 收录视频,但是未提供在线播放资源 */
|
||||
videoQuery?: string;
|
||||
subQuery?: string;
|
||||
leakQuery?: string;
|
||||
}
|
||||
|
||||
export interface SiteItem_get {
|
||||
name: string;
|
||||
disable?: string;
|
||||
hostname: string;
|
||||
url: string;
|
||||
fetcher: "get";
|
||||
domQuery: DomQuery_get;
|
||||
codeFormater?: (arg0: string) => string;
|
||||
method?: Function;
|
||||
}
|
||||
|
||||
export interface SiteItem_parser {
|
||||
name: string;
|
||||
disable?: string;
|
||||
hostname: string;
|
||||
url: string;
|
||||
fetcher: "parser";
|
||||
domQuery: DomQuery_parser;
|
||||
codeFormater?: (arg0: string) => string;
|
||||
method?: Function;
|
||||
}
|
||||
|
||||
export type SiteItem = SiteItem_get | SiteItem_parser;
|
||||
|
||||
const print = (name: string) => {
|
||||
console.log(name);
|
||||
};
|
||||
|
||||
/** 网站列表 */
|
||||
export const siteList: SiteItem[] = [
|
||||
{
|
||||
name: "Jable",
|
||||
hostname: "jable.tv",
|
||||
url: "https://jable.tv/videos/{{code}}/",
|
||||
fetcher: "get",
|
||||
domQuery: { subQuery: ".header-right>h6" },
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "MISSAV",
|
||||
hostname: "missav.com",
|
||||
url: "https://missav.com/{{code}}/",
|
||||
fetcher: "get",
|
||||
domQuery: {
|
||||
/** 标签区的第一个一般是字幕标签 */
|
||||
subQuery: '.space-y-2 a.text-nord13[href="https://missav.com/chinese-subtitle"]',
|
||||
/** videoPage 有个跳转按钮 */
|
||||
leakQuery: ".order-first div.rounded-md a[href]:last-child",
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "NETFLAV",
|
||||
hostname: "netflav.com",
|
||||
url: "https://netflav.com/search?type=title&keyword={{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: { linkQuery: ".grid_cell>a", titleQuery: ".grid_cell>a>.grid_title" },
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "Avgle",
|
||||
hostname: "avgle.com",
|
||||
url: "https://avgle.com/search/videos?search_query={{code}}&search_type=videos",
|
||||
fetcher: "parser",
|
||||
domQuery: {
|
||||
linkQuery: ".container>.row .row .well>a[href]",
|
||||
titleQuery: ".container>.row .row .well .video-title",
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "JAVHHH",
|
||||
hostname: "javhhh.com",
|
||||
url: "https://javhhh.com/v/?wd={{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: {
|
||||
linkQuery: ".typelist>.i-container>a[href]",
|
||||
titleQuery: ".typelist>.i-container>a[href]",
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "BestJP",
|
||||
hostname: "bestjavporn.com",
|
||||
url: "https://www3.bestjavporn.com/search/{{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: { linkQuery: "article.thumb-block>a", titleQuery: "article.thumb-block>a" },
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "JAVMENU",
|
||||
hostname: "javmenu.com",
|
||||
url: "https://javmenu.com/{{code}}",
|
||||
fetcher: "get",
|
||||
domQuery: {
|
||||
videoQuery: "a.nav-link[aria-controls='pills-0']",
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "Jav.Guru",
|
||||
hostname: "jav.guru",
|
||||
url: "https://jav.guru/?s={{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: { linkQuery: ".imgg>a[href]", titleQuery: ".inside-article>.grid1 a[title]" },
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "JAVMOST",
|
||||
hostname: "javmost.cx",
|
||||
url: "https://javmost.cx/search/{{code}}/",
|
||||
fetcher: "parser",
|
||||
domQuery: {
|
||||
linkQuery: "#content .card a#MyImage",
|
||||
titleQuery: "#content .card-block .card-title",
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "JAVFC2",
|
||||
hostname: "javfc2.net",
|
||||
url: "https://javfc2.net/?s={{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: {
|
||||
linkQuery: "article.loop-video>a[href]",
|
||||
titleQuery: "article.loop-video .entry-header",
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "baihuse",
|
||||
hostname: "paipancon.com",
|
||||
url: "https://paipancon.com/search/{{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: {
|
||||
linkQuery: "div.col>div.card>a[href]",
|
||||
// 然而这个不是 title,是图片,这个站居然 title 里不包含 code,反而图片包含
|
||||
titleQuery: "div.card img.card-img-top",
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "GGJAV",
|
||||
hostname: "ggjav.com",
|
||||
url: "https://ggjav.com/main/search?string={{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: {
|
||||
listIndex: 1,
|
||||
spaceCode: true,
|
||||
titleQuery: "div.columns.large-3.medium-6.small-12.item.float-left>div.item_title>a.gray_a",
|
||||
linkQuery: "div.columns.large-3.medium-6.small-12.item.float-left>div.item_title>a.gray_a",
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
|
||||
{
|
||||
name: "AV01",
|
||||
hostname: "av01.tv",
|
||||
url: "https://www.av01.tv/search/videos?search_query={{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: { linkQuery: "div[id].well-sm>a", titleQuery: ".video-views>.pull-left" },
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "JavBus",
|
||||
disable: "javbus",
|
||||
hostname: "javbus.com",
|
||||
url: "https://javbus.com/{{code}}",
|
||||
fetcher: "get",
|
||||
domQuery: {},
|
||||
method: print,
|
||||
},
|
||||
// {
|
||||
// name: "JavDB",
|
||||
// disable:"javdb",
|
||||
// hostname: "javbus.com",
|
||||
// url: "https://javbus.com/{{code}}",
|
||||
// fetcher: "get",
|
||||
// domQuery: {},
|
||||
// method: print,
|
||||
// },
|
||||
];
|
||||
101
src/style.css
Normal file
101
src/style.css
Normal file
@@ -0,0 +1,101 @@
|
||||
.jop-panel {
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
top: 37.5%;
|
||||
right: -305px;
|
||||
width: 330px;
|
||||
height: 400px;
|
||||
padding: 35px 35px 35px 60px;
|
||||
border-radius: 15px 0 0 15px;
|
||||
background-color: white;
|
||||
box-shadow: rgb(0 0 0 / 26%) 3px 0px 8px;
|
||||
transition: right 200ms ease-in-out;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 10px 0;
|
||||
}
|
||||
.jop-panel_open {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.jop-button {
|
||||
display: inline-flex;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
background-color: transparent;
|
||||
outline: 0px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
vertical-align: middle;
|
||||
appearance: none;
|
||||
text-decoration: none;
|
||||
font-family: Roboto, Helvetica, Arial, sans-serif;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 1.75;
|
||||
letter-spacing: 0.02857em;
|
||||
min-width: 110px;
|
||||
padding: 5px 15px;
|
||||
border-radius: 8px;
|
||||
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
|
||||
box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
|
||||
border-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
|
||||
color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||
color: #606266;
|
||||
border: 1px solid #dcdfe6;
|
||||
}
|
||||
.jop-button:visited {
|
||||
color: #606266;
|
||||
}
|
||||
.jop-button:hover {
|
||||
text-decoration: none;
|
||||
color: #409eff;
|
||||
border: 1px solid #c6e2ff;
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
|
||||
.jop-button-loading {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-top-color: transparent;
|
||||
border-radius: 100%;
|
||||
animation: btnLoading infinite 0.75s linear;
|
||||
}
|
||||
|
||||
.jop-button_green {
|
||||
color: #67c23a !important;
|
||||
background-color: #f0f9eb;
|
||||
border: 1px solid #b3e19d;
|
||||
}
|
||||
.jop-button_green:hover {
|
||||
color: white !important;
|
||||
background-color: #67c23a;
|
||||
}
|
||||
|
||||
.jop-button_red {
|
||||
color: #f56c6c !important;
|
||||
background-color: #fef0f0;
|
||||
border: 1px solid #fab6b6;
|
||||
}
|
||||
.jop-button_red:hover {
|
||||
color: white !important;
|
||||
background-color: #f56c6c;
|
||||
}
|
||||
|
||||
@keyframes btnLoading {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
35
src/vite-env.d.ts
vendored
Normal file
35
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
/**
|
||||
* alias of vite-plugin-monkey/dist/client
|
||||
*/
|
||||
declare module '$' {
|
||||
export * from 'vite-plugin-monkey/dist/client';
|
||||
}
|
||||
|
||||
// if set mountGmApi=true
|
||||
// type MonkeyWindow = import('vite-plugin-monkey/dist/client').MonkeyWindow;
|
||||
// declare const unsafeWindow: MonkeyWindow['unsafeWindow'];
|
||||
// declare const GM_addStyle: MonkeyWindow['GM_addStyle'];
|
||||
// declare const GM_addElement: MonkeyWindow['GM_addElement'];
|
||||
// declare const GM_deleteValue: MonkeyWindow['GM_deleteValue'];
|
||||
// declare const GM_listValues: MonkeyWindow['GM_listValues'];
|
||||
// declare const GM_addValueChangeListener: MonkeyWindow['GM_addValueChangeListener'];
|
||||
// declare const GM_removeValueChangeListener: MonkeyWindow['GM_removeValueChangeListener'];
|
||||
// declare const GM_setValue: MonkeyWindow['GM_setValue'];
|
||||
// declare const GM_getValue: MonkeyWindow['GM_getValue'];
|
||||
// declare const GM_log: MonkeyWindow['GM_log'];
|
||||
// declare const GM_getResourceText: MonkeyWindow['GM_getResourceText'];
|
||||
// declare const GM_getResourceURL: MonkeyWindow['GM_getResourceURL'];
|
||||
// declare const GM_registerMenuCommand: MonkeyWindow['GM_registerMenuCommand'];
|
||||
// declare const GM_unregisterMenuCommand: MonkeyWindow['GM_unregisterMenuCommand'];
|
||||
// declare const GM_openInTab: MonkeyWindow['GM_openInTab'];
|
||||
// declare const GM_xmlhttpRequest: MonkeyWindow['GM_xmlhttpRequest'];
|
||||
// declare const GM_download: MonkeyWindow['GM_download'];
|
||||
// declare const GM_getTab: MonkeyWindow['GM_getTab'];
|
||||
// declare const GM_saveTab: MonkeyWindow['GM_saveTab'];
|
||||
// declare const GM_getTabs: MonkeyWindow['GM_getTabs'];
|
||||
// declare const GM_notification: MonkeyWindow['GM_notification'];
|
||||
// declare const GM_setClipboard: MonkeyWindow['GM_setClipboard'];
|
||||
// declare const GM_info: MonkeyWindow['GM_info'];
|
||||
// declare const GM_cookie: MonkeyWindow['GM_cookie'];
|
||||
129
src/xhr.ts
Normal file
129
src/xhr.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { GM_xmlhttpRequest } from "$";
|
||||
import type { DomQuery_get, DomQuery_parser, SiteItem } from "./siteList";
|
||||
|
||||
/** 针对视频播放页进行解析,寻找字幕等信息 */
|
||||
function videoPageParser(responseText: string, { subQuery, leakQuery, videoQuery }: DomQuery_get) {
|
||||
const doc = new DOMParser().parseFromString(responseText, "text/html");
|
||||
|
||||
const subNode = subQuery ? doc.querySelector<HTMLElement>(subQuery) : "";
|
||||
const subNodeText = subNode ? subNode.innerHTML : "";
|
||||
const leakNode = leakQuery ? doc.querySelector<HTMLElement>(leakQuery) : null;
|
||||
// 部分网站收录视频,但是未提供播放资源,所以需要使用 videoQuery 进一步检测是否存在在线播放
|
||||
/** videoQuery 为 undefine 时,不需要查找 video */
|
||||
const videoNode = videoQuery ? doc.querySelector<HTMLElement>(videoQuery) : true;
|
||||
|
||||
return {
|
||||
isSuccess: !!videoNode,
|
||||
hasSubtitle: subNodeText.includes("字幕") || subNodeText.includes("subtitle"),
|
||||
hasLeakage: !!leakNode,
|
||||
};
|
||||
}
|
||||
|
||||
/** 针对 fetcher==="parser" 时的搜索结果页进行解析,寻找是否存在视频资源。
|
||||
* linkQuery、titleQuery 都是必须,
|
||||
* linkQuery 有结果且 titleQuery 结果包含 code,返回 isSuccess。
|
||||
* 再检查下 title 中是否含有字幕信息等
|
||||
*/
|
||||
function serachPageParser(
|
||||
responseText: string,
|
||||
{ linkQuery, titleQuery, listIndex = 0, spaceCode = false }: DomQuery_parser,
|
||||
siteHostName: string,
|
||||
CODE: string,
|
||||
) {
|
||||
const doc = new DOMParser().parseFromString(responseText, "text/html");
|
||||
|
||||
const linkNode = linkQuery ? doc.querySelectorAll<HTMLAnchorElement>(linkQuery)[listIndex] : null;
|
||||
const titleNode = titleQuery ? doc.querySelectorAll(titleQuery)[listIndex] : null;
|
||||
const titleNodeText = titleNode ? titleNode?.outerHTML : "";
|
||||
|
||||
function query() {
|
||||
/** 空格版本的 code */
|
||||
const envCodeWithSpace = spaceCode ? CODE.replace("-", " ") : CODE;
|
||||
const condition =
|
||||
linkNode &&
|
||||
titleNode &&
|
||||
(titleNodeText.includes(envCodeWithSpace) || titleNodeText.includes(CODE));
|
||||
|
||||
if (condition) {
|
||||
return {
|
||||
isSuccess: true,
|
||||
targetLink: linkNode.href.replace(linkNode.hostname, siteHostName),
|
||||
hasLeakage: titleNodeText.includes("无码") || titleNodeText.includes("Uncensored"),
|
||||
hasSubtitle: titleNodeText.includes("字幕") || titleNodeText.includes("subtitle"),
|
||||
};
|
||||
} else {
|
||||
return { targetLink: "", isSuccess: false };
|
||||
}
|
||||
}
|
||||
return query();
|
||||
}
|
||||
|
||||
export async function xhr(siteItem: SiteItem, siteUrl: string, CODE: string) {
|
||||
const xhrPromise: Promise<{
|
||||
isSuccess: boolean;
|
||||
targetLink: string;
|
||||
name: string;
|
||||
hasSubtitle?: boolean;
|
||||
hasLeakage?: boolean;
|
||||
msg: string;
|
||||
}> = new Promise((resolve) => {
|
||||
GM_xmlhttpRequest({
|
||||
method: "GET",
|
||||
url: siteUrl,
|
||||
onload: (response) => {
|
||||
if (siteItem.fetcher === "get") {
|
||||
// 直接 get 网页,且 get 结果为 404,大概是对应网站没有资源
|
||||
if (response.status === 404) {
|
||||
resolve({
|
||||
isSuccess: false,
|
||||
targetLink: siteUrl,
|
||||
name: siteItem.name,
|
||||
msg: "应该是没有资源",
|
||||
});
|
||||
}
|
||||
// 直接 get 网页,成功,需要进一步解析 videoPage,获取字幕等信息
|
||||
else {
|
||||
const { hasSubtitle, hasLeakage, isSuccess } = videoPageParser(
|
||||
response.responseText,
|
||||
siteItem.domQuery,
|
||||
);
|
||||
resolve({
|
||||
isSuccess,
|
||||
targetLink: siteUrl,
|
||||
name: siteItem.name,
|
||||
hasSubtitle,
|
||||
hasLeakage,
|
||||
msg: "[get],存在资源",
|
||||
});
|
||||
}
|
||||
}
|
||||
// 需要解析 searchPage
|
||||
else if (siteItem.fetcher === "parser") {
|
||||
const { targetLink, isSuccess, hasLeakage, hasSubtitle } = serachPageParser(
|
||||
response.responseText,
|
||||
siteItem.domQuery,
|
||||
siteItem.hostname,
|
||||
CODE,
|
||||
);
|
||||
resolve({
|
||||
name: siteItem.name,
|
||||
isSuccess,
|
||||
targetLink: isSuccess ? targetLink : siteUrl,
|
||||
hasSubtitle,
|
||||
hasLeakage,
|
||||
msg: "[parser]存在资源",
|
||||
});
|
||||
}
|
||||
},
|
||||
onerror: (error) => {
|
||||
resolve({
|
||||
isSuccess: false,
|
||||
targetLink: siteUrl,
|
||||
name: siteItem.name,
|
||||
msg: error.error,
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
return xhrPromise;
|
||||
}
|
||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"noEmit": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
44
vite.config.ts
Normal file
44
vite.config.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { defineConfig } from "vite";
|
||||
import monkey, { MonkeyUserScript } from "vite-plugin-monkey";
|
||||
|
||||
const UserscriptConfig: MonkeyUserScript = {
|
||||
author: "mission522",
|
||||
version: "1.0.0",
|
||||
license: "MIT",
|
||||
name: "JAV 添加跳转在线观看 三合一",
|
||||
match: ["*://*.javdb.com/*", "*://*.javbus.com/*", "*://*.javlibrary.com/*"],
|
||||
include: /^https:\/\/(\w*\.)?javdb(\d)*\.com.*$/,
|
||||
icon: "https://javdb.com/favicon-32x32.png",
|
||||
namespace: "https://greasyfork.org/users/58790",
|
||||
description:
|
||||
"在 JavDB、JavBus、JavLibrart 网站的影片详情页添加跳转在线播放按钮,并在按钮上标注是否存在可播放资源,资源是否为「字幕」、「无码」等信息。",
|
||||
connect: [
|
||||
"jable.tv",
|
||||
"missav.com",
|
||||
"javhhh.com",
|
||||
"netflav.com",
|
||||
"avgle.com",
|
||||
"bestjavporn.com",
|
||||
"jav.guru",
|
||||
"javmost.cx",
|
||||
"hpjav.tv",
|
||||
"av01.tv",
|
||||
"javbus.com",
|
||||
"javmenu.com",
|
||||
"javfc2.net",
|
||||
"paipancon.com",
|
||||
"ggjav.com",
|
||||
],
|
||||
};
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
monkey({
|
||||
entry: "src/index.ts",
|
||||
build: { fileName: "jop.user.js" },
|
||||
userscript: {
|
||||
...UserscriptConfig,
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
Reference in New Issue
Block a user