feat: migrate to plasmo
@@ -1,5 +0,0 @@
|
||||
.github/
|
||||
.vscode/
|
||||
dist
|
||||
release
|
||||
*.config.js
|
||||
@@ -1,64 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"plugins": [
|
||||
"prettier"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"rules": {
|
||||
"no-console": 0,
|
||||
"block-scoped-var": 1,
|
||||
"curly": 1,
|
||||
"eqeqeq": 1,
|
||||
"no-global-assign": 1,
|
||||
"no-implicit-globals": 1,
|
||||
"no-labels": 1,
|
||||
"no-multi-str": 1,
|
||||
"comma-spacing": 1,
|
||||
"comma-style": 1,
|
||||
"func-call-spacing": 1,
|
||||
"keyword-spacing": 1,
|
||||
"linebreak-style": 1,
|
||||
"lines-around-comment": 1,
|
||||
"no-multiple-empty-lines": 1,
|
||||
"space-infix-ops": 1,
|
||||
"arrow-spacing": 1,
|
||||
"no-var": 1,
|
||||
"prefer-const": 1,
|
||||
"no-unsafe-negation": 1,
|
||||
"array-callback-return": 1,
|
||||
"dot-notation": 1,
|
||||
"no-eval": 0,
|
||||
"no-extend-native": 1,
|
||||
"no-extra-label": 1,
|
||||
"semi": 1,
|
||||
"space-before-blocks": 1,
|
||||
"space-in-parens": 1,
|
||||
"space-unary-ops": 1,
|
||||
"spaced-comment": 1,
|
||||
"arrow-body-style": 1,
|
||||
"arrow-parens": 1,
|
||||
"no-restricted-imports": 1,
|
||||
"no-duplicate-imports": 1,
|
||||
"no-useless-computed-key": 1,
|
||||
"no-useless-rename": 1,
|
||||
"rest-spread-spacing": 1,
|
||||
"no-trailing-spaces": 1,
|
||||
"no-control-regex": 0,
|
||||
"prettier/prettier": 0,
|
||||
"no-await-in-loop": 1,
|
||||
"require-atomic-updates": 0,
|
||||
"no-prototype-builtins": 0,
|
||||
"no-undef": 0,
|
||||
"vue/no-use-v-if-with-v-for": "off",
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "21:00"
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- DIYgod
|
||||
labels:
|
||||
- dependencies
|
||||
ignore:
|
||||
- dependency-name: webpack
|
||||
versions:
|
||||
- 5.26.2
|
||||
- 5.27.2
|
||||
- 5.28.0
|
||||
- 5.28.0
|
||||
- 5.30.0
|
||||
- 5.31.0
|
||||
- 5.31.2
|
||||
- 5.35.0
|
||||
- 5.35.1
|
||||
- dependency-name: webpack-cli
|
||||
versions:
|
||||
- 4.4.0
|
||||
- 4.5.0
|
||||
- 4.5.0
|
||||
- 4.5.0
|
||||
- 4.6.0
|
||||
- 4.6.0
|
||||
- 4.6.0
|
||||
- 4.6.0
|
||||
- dependency-name: copy-webpack-plugin
|
||||
versions:
|
||||
- 8.1.0
|
||||
- dependency-name: postcss-loader
|
||||
versions:
|
||||
- 5.1.0
|
||||
@@ -1,43 +0,0 @@
|
||||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build assets
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
run: |
|
||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
- name: Install dependencies
|
||||
run: pnpm i
|
||||
- name: Build file
|
||||
run: pnpm run release
|
||||
- name: Upload file
|
||||
uses: xresloader/upload-to-github-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
file: "release/radar.zip"
|
||||
tags: true
|
||||
draft: false
|
||||
@@ -0,0 +1,34 @@
|
||||
name: "Submit to Web Store"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache pnpm modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.pnpm-store
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
with:
|
||||
version: latest
|
||||
run_install: true
|
||||
- name: Use Node.js 16.x
|
||||
uses: actions/setup-node@v3.4.1
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: "pnpm"
|
||||
- name: Build the extension
|
||||
run: pnpm build
|
||||
- name: Package the extension into a zip artifact
|
||||
run: pnpm package
|
||||
- name: Browser Platform Publish
|
||||
uses: PlasmoHQ/bpp@v3
|
||||
with:
|
||||
keys: ${{ secrets.SUBMIT_KEYS }}
|
||||
artifact: build/chrome-mv3-prod.zip
|
||||
@@ -1,4 +1,39 @@
|
||||
node_modules
|
||||
dist
|
||||
release
|
||||
yarn-error.log
|
||||
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
#cache
|
||||
.turbo
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
.env*
|
||||
|
||||
out/
|
||||
build/
|
||||
dist/
|
||||
|
||||
# plasmo - https://www.plasmo.com
|
||||
.plasmo
|
||||
|
||||
# bpp - http://bpp.browser.market/
|
||||
keys.json
|
||||
|
||||
# typescript
|
||||
.tsbuildinfo
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package.json
|
||||
package-lock.json
|
||||
.github/
|
||||
.vscode/
|
||||
dist
|
||||
release
|
||||
*.config.js
|
||||
src/js/common/radar-rules.js
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"printWidth": 233,
|
||||
"tabWidth": 4,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"arrowParens": "always"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @type {import('prettier').Options}
|
||||
*/
|
||||
export default {
|
||||
printWidth: 80,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
semi: false,
|
||||
singleQuote: false,
|
||||
trailingComma: "none",
|
||||
bracketSpacing: true,
|
||||
bracketSameLine: true,
|
||||
plugins: ["@ianvs/prettier-plugin-sort-imports"],
|
||||
importOrder: [
|
||||
"<BUILTIN_MODULES>", // Node.js built-in modules
|
||||
"<THIRD_PARTY_MODULES>", // Imports not matched by other special words or groups.
|
||||
"", // Empty line
|
||||
"^@plasmo/(.*)$",
|
||||
"",
|
||||
"^@plasmohq/(.*)$",
|
||||
"",
|
||||
"^~(.*)$",
|
||||
"",
|
||||
"^[./]"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
This is a [Plasmo extension](https://docs.plasmo.com/) project bootstrapped with [`plasmo init`](https://www.npmjs.com/package/plasmo).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
# or
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Open your browser and load the appropriate development build. For example, if you are developing for the chrome browser, using manifest v3, use: `build/chrome-mv3-dev`.
|
||||
|
||||
You can start editing the popup by modifying `popup.tsx`. It should auto-update as you make changes. To add an options page, simply add a `options.tsx` file to the root of the project, with a react component default exported. Likewise to add a content page, add a `content.ts` file to the root of the project, importing some module and do some logic, then reload the extension on your browser.
|
||||
|
||||
For further guidance, [visit our Documentation](https://docs.plasmo.com/)
|
||||
|
||||
## Making production build
|
||||
|
||||
Run the following:
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
# or
|
||||
npm run build
|
||||
```
|
||||
|
||||
This should create a production bundle for your extension, ready to be zipped and published to the stores.
|
||||
|
||||
## Submit to the webstores
|
||||
|
||||
The easiest way to deploy your Plasmo extension is to use the built-in [bpp](https://bpp.browser.market) GitHub action. Prior to using this action however, make sure to build your extension and upload the first version to the store to establish the basic credentials. Then, simply follow [this setup instruction](https://docs.plasmo.com/framework/workflows/submit) and you should be on your way for automated submission!
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -1,83 +1,38 @@
|
||||
{
|
||||
"name": "rsshub-radar",
|
||||
"version": "0.0.1",
|
||||
"description": "Browser extension to detect available RSS and RSSHub for current page",
|
||||
"displayName": "RSSHub Radar",
|
||||
"version": "2.0.0",
|
||||
"description": "Browser extension that simplifies finding and subscribing RSS and RSSHub",
|
||||
"author": "DIYgod <i@diygod.me>",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"dev": "webpack -w --mode=production --progress",
|
||||
"build": "webpack --mode=production --progress",
|
||||
"release": "npm run build && mkdir release && zip -r release/radar.zip dist",
|
||||
"format": "eslint \"**/*.js\" --fix && prettier \"**/*.{js,scss,less}\" --write",
|
||||
"format:staged": "eslint \"**/*.js\" --fix && pretty-quick --staged --verbose --pattern \"**/*.{js,scss,less}\"",
|
||||
"format:check": "eslint \"**/*.js\" && prettier-check \"**/*.{js,scss,less}\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/DIYgod/RSSHub-Radar.git"
|
||||
},
|
||||
"keywords": [
|
||||
"rsshub",
|
||||
"rss"
|
||||
],
|
||||
"gitHooks": {
|
||||
"pre-commit": "npm run format:staged"
|
||||
},
|
||||
"author": "DIYgod",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/DIYgod/RSSHub-Radar/issues"
|
||||
},
|
||||
"homepage": "https://github.com/DIYgod/RSSHub-Radar#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.23.3",
|
||||
"@babel/preset-env": "7.23.3",
|
||||
"autoprefixer": "10.4.16",
|
||||
"babel-loader": "9.1.3",
|
||||
"babel-plugin-component": "1.1.1",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"css-loader": "6.8.1",
|
||||
"cssnano": "5.1.14",
|
||||
"eslint": "8.54.0",
|
||||
"eslint-config-prettier": "9.0.0",
|
||||
"eslint-loader": "4.0.2",
|
||||
"eslint-plugin-prettier": "5.0.1",
|
||||
"file-loader": "6.2.0",
|
||||
"less": "4.2.0",
|
||||
"less-loader": "11.1.3",
|
||||
"mini-css-extract-plugin": "2.7.6",
|
||||
"postcss-loader": "7.3.3",
|
||||
"prettier": "2.8.3",
|
||||
"prettier-check": "2.0.0",
|
||||
"pretty-quick": "3.1.3",
|
||||
"sass": "^1.69.5",
|
||||
"sass-loader": "13.3.2",
|
||||
"svg-inline-loader": "0.8.2",
|
||||
"template-string-optimize-loader": "3.0.0",
|
||||
"url-loader": "4.1.1",
|
||||
"vue-loader": "15.10.1",
|
||||
"vue-style-loader": "^4.1.3",
|
||||
"vue-template-compiler": "2.7.15",
|
||||
"webpack": "5.89.0",
|
||||
"webpack-cli": "5.1.4",
|
||||
"yorkie": "2.0.0"
|
||||
"dev": "plasmo dev",
|
||||
"build": "plasmo build",
|
||||
"package": "plasmo package"
|
||||
},
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"clipboard": "2.0.11",
|
||||
"element-ui": "2.15.14",
|
||||
"https-browserify": "^1.0.0",
|
||||
"i18n-js": "^4.3.2",
|
||||
"lodash": "^4.17.21",
|
||||
"md5.js": "^1.3.5",
|
||||
"process": "^0.11.10",
|
||||
"psl": "1.9.0",
|
||||
"route-recognizer": "0.3.4",
|
||||
"rss-parser": "3.13.0",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"stream-http": "^3.2.0",
|
||||
"timers-browserify": "^2.0.12",
|
||||
"url": "^0.11.3",
|
||||
"vue": "2",
|
||||
"vue-router": "3.6.5"
|
||||
"@plasmohq/messaging": "^0.6.1",
|
||||
"plasmo": "0.84.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ianvs/prettier-plugin-sort-imports": "4.1.1",
|
||||
"@types/chrome": "0.0.251",
|
||||
"@types/node": "20.9.0",
|
||||
"@types/react": "18.2.37",
|
||||
"@types/react-dom": "18.2.15",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"postcss": "^8.4.32",
|
||||
"prettier": "3.0.3",
|
||||
"tailwindcss": "^3.3.6",
|
||||
"typescript": "5.2.2"
|
||||
},
|
||||
"manifest": {
|
||||
"host_permissions": [
|
||||
"https://*/*"
|
||||
],
|
||||
"permissions": [
|
||||
"tabs"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* @type {import('postcss').ProcessOptions}
|
||||
*/
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"config:base"
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>RSSHub Radar Background</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="sandbox" src="sandbox.html"></iframe>
|
||||
<script src="background.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "i@diygod.me"
|
||||
}
|
||||
},
|
||||
"name": "RSSHub Radar",
|
||||
"description": "RSSHub Radar is a spin-off of RSSHub that helps you quickly discover and subscribe to RSS and RSSHub for your current site.",
|
||||
"version": "1.10.3",
|
||||
"homepage_url": "https://docs.rsshub.app",
|
||||
"icons": {
|
||||
"16": "icon16.png",
|
||||
"48": "icon48.png",
|
||||
"128": "icon128.png"
|
||||
},
|
||||
|
||||
"browser_action": {
|
||||
"default_icon": "rsshub.png",
|
||||
"default_popup": "popup.html"
|
||||
},
|
||||
"content_scripts": [{
|
||||
"matches": ["https://*/*", "http://*/*"],
|
||||
"js": ["content.js"]
|
||||
}],
|
||||
"background" : {
|
||||
"page": "background.html",
|
||||
"persistent": true
|
||||
},
|
||||
"options_page": "options.html",
|
||||
"sandbox": {
|
||||
"pages": ["sandbox.html"]
|
||||
},
|
||||
"permissions": [
|
||||
"tabs",
|
||||
"storage",
|
||||
"notifications",
|
||||
"alarms",
|
||||
"idle"
|
||||
]
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title data-i18n>RSSHub Radar Options</title>
|
||||
<link rel="stylesheet" href="./options.css">
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="sandbox" style="display: none;" src="sandbox.html"></iframe>
|
||||
<div id="app"></div>
|
||||
<script src="./options.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,30 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>RSSHub Radar</title>
|
||||
<link rel="stylesheet" href="./popup.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="icons">
|
||||
<a class="icons-item icons-about" href="/options.html#/about"></a>
|
||||
<a class="icons-item icons-setting" href="/options.html#/setting"></a>
|
||||
</div>
|
||||
<div class="no-rss">
|
||||
<h2>( ´・・)ノ(._.`) <span data-i18n>rss not found</span></h2>
|
||||
<p data-i18n>join rsshub</p>
|
||||
</div>
|
||||
<div class="page-rss">
|
||||
<h2 data-i18n>current page rss</h2>
|
||||
<ul></ul>
|
||||
</div>
|
||||
<div class="page-rsshub">
|
||||
<h2 data-i18n>current page RSSHub</h2>
|
||||
<ul></ul>
|
||||
</div>
|
||||
<div class="website-rsshub">
|
||||
<h2 data-i18n>current site RSSHub</h2>
|
||||
<ul></ul>
|
||||
</div>
|
||||
<script src="./popup.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,9 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>RSSHub Radar Sandbox</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="sandbox.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,2 @@
|
||||
export {}
|
||||
console.log("HELLO WORLD FROM BGSCRIPTS")
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { PlasmoCSConfig } from "plasmo"
|
||||
|
||||
export const config: PlasmoCSConfig = {
|
||||
matches: ["https://www.plasmo.com/*"]
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
console.log("content script loaded")
|
||||
|
||||
document.body.style.background = "pink"
|
||||
})
|
||||
@@ -1,5 +0,0 @@
|
||||
$--color-primary: #f5712c;
|
||||
|
||||
$--font-path: '~element-ui/lib/theme-chalk/fonts';
|
||||
|
||||
@import '~element-ui/packages/theme-chalk/src/index';
|
||||
@@ -1,262 +0,0 @@
|
||||
body {
|
||||
min-width: 350px;
|
||||
margin: 0;
|
||||
padding: 20px 20px 5px;
|
||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
|
||||
|
||||
&.something {
|
||||
.no-rss {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.icons {
|
||||
right: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icons {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 21px;
|
||||
|
||||
.icons-item {
|
||||
width: 18px;
|
||||
display: inline-block;
|
||||
fill: #666;
|
||||
transition: 0.3s;
|
||||
margin-left: 5px;
|
||||
|
||||
&:hover {
|
||||
fill: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-rss,
|
||||
.page-rsshub,
|
||||
.website-rsshub {
|
||||
display: none;
|
||||
margin-bottom: 20px;
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
margin: 0 0 15px;
|
||||
}
|
||||
|
||||
ul,
|
||||
li {
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.no-rss {
|
||||
margin-bottom: 20px;
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
margin: 0 0 15px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #ff8549;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
.rss-item {
|
||||
display: flex;
|
||||
height: 30px;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.rss-image {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.rss-info {
|
||||
width: 200px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
line-height: 1;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.rss-title {
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.rss-url {
|
||||
font-size: 12px;
|
||||
color: #aaa;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.rss-action {
|
||||
white-space: nowrap;
|
||||
padding: 0 10px;
|
||||
font-size: 13px;
|
||||
color: #f5712c;
|
||||
background: #fff;
|
||||
border: 1px solid #f5712c;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
transition: 0.3s;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
text-decoration: none;
|
||||
margin-left: 10px;
|
||||
min-width: 61px;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #f5712c;
|
||||
}
|
||||
|
||||
&.rss-copy {
|
||||
width: 61px;
|
||||
}
|
||||
|
||||
&.rss-submitto-ttrss {
|
||||
color: #f28f34;
|
||||
border: 1px solid #f28f34;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #f28f34;
|
||||
}
|
||||
}
|
||||
|
||||
&.rss-submitto-checkchan {
|
||||
color: #f28f34;
|
||||
border: 1px solid #f28f34;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #f28f34;
|
||||
}
|
||||
}
|
||||
|
||||
&.rss-submitto-miniflux {
|
||||
color: #33995b;
|
||||
border: 1px solid #33995b;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #33995b;
|
||||
}
|
||||
}
|
||||
|
||||
&.rss-submitto-freshrss {
|
||||
color: #0062bd;
|
||||
border: 1px solid #0062db;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #0062db;
|
||||
}
|
||||
}
|
||||
|
||||
&.rss-submitto-nextcloudnews {
|
||||
color: #0082c9;
|
||||
border: 1px solid #0082c9;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #0082c9;
|
||||
}
|
||||
}
|
||||
|
||||
&.rss-submitto-feedly {
|
||||
color: #2bb24c;
|
||||
border: 1px solid #2bb24c;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #2bb24c;
|
||||
}
|
||||
}
|
||||
|
||||
&.rss-submitto-inoreader {
|
||||
color: #0099eb;
|
||||
border: 1px solid #0099eb;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #0099eb;
|
||||
}
|
||||
}
|
||||
|
||||
&.rss-submitto-feedbin {
|
||||
color: #0867e2;
|
||||
border: 1px solid #0867e2;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #0867e2;
|
||||
}
|
||||
}
|
||||
|
||||
&.rss-submitto-theoldreader {
|
||||
color: #ff2300;
|
||||
border: 1px solid #ff2300;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #ff2300;
|
||||
}
|
||||
}
|
||||
|
||||
&.rss-submitto-feedspub {
|
||||
color: #61af4b;
|
||||
border: 1px solid #61af4b;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #61af4b;
|
||||
}
|
||||
}
|
||||
|
||||
&.rss-submitto-bazqux {
|
||||
color: #00af00;
|
||||
border: 1px solid #00af00;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: #00af00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.website-rsshub {
|
||||
.rss-info {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.rss-action {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
import { handleRSS, removeRSS, addPageRSS, getAllRSS } from './utils';
|
||||
import { getConfig, saveConfig } from '../common/config';
|
||||
|
||||
chrome.tabs.onActivated.addListener((tab) => {
|
||||
chrome.tabs.sendMessage(
|
||||
tab.tabId,
|
||||
{
|
||||
text: 'getPageRSS',
|
||||
},
|
||||
(feeds) => {
|
||||
handleRSS(feeds, tab.tabId, true);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
|
||||
if (changeInfo.url && tab.active) {
|
||||
chrome.tabs.sendMessage(
|
||||
tab.id,
|
||||
{
|
||||
text: 'getPageRSS',
|
||||
},
|
||||
(feeds) => {
|
||||
handleRSS(feeds, tab.id);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
if (sender.tab && sender.tab.active) {
|
||||
if (msg.text === 'setPageRSS') {
|
||||
handleRSS(msg.feeds, sender.tab.id);
|
||||
} else if (msg.text === 'addPageRSS') {
|
||||
addPageRSS(msg.feed, sender.tab.id);
|
||||
}
|
||||
}
|
||||
if (msg.text === 'getAllRSS') {
|
||||
sendResponse(getAllRSS(msg.tabId));
|
||||
}
|
||||
});
|
||||
|
||||
chrome.tabs.onRemoved.addListener((tabId) => {
|
||||
removeRSS(tabId);
|
||||
});
|
||||
|
||||
getConfig((config) => {
|
||||
if (!config.version) {
|
||||
config.version = VERSION;
|
||||
saveConfig(config);
|
||||
} else if (config.version !== VERSION) {
|
||||
chrome.notifications.create('RSSHubRadarUpdate', {
|
||||
type: 'basic',
|
||||
iconUrl: './rsshub.png',
|
||||
title: '🎉 RSSHub Radar 更新',
|
||||
message: `v${VERSION},点击查看更新日志`,
|
||||
});
|
||||
chrome.notifications.onClicked.addListener((id) => {
|
||||
if (id === 'RSSHubRadarUpdate') {
|
||||
chrome.tabs.create({
|
||||
url: 'https://github.com/DIYgod/RSSHub-Radar/releases',
|
||||
});
|
||||
chrome.notifications.clear('RSSHubRadarUpdate');
|
||||
}
|
||||
});
|
||||
config.version = VERSION;
|
||||
saveConfig(config);
|
||||
}
|
||||
});
|
||||
@@ -1,171 +0,0 @@
|
||||
import { getRules, getRulesDate, refreshRules } from '../common/rules';
|
||||
import { commandSandbox } from '../common/utils';
|
||||
import { getConfig } from '../common/config';
|
||||
let config;
|
||||
let rules = {};
|
||||
import RSSParser from 'rss-parser';
|
||||
const rssParser = new RSSParser();
|
||||
|
||||
window.pageRSS = {};
|
||||
window.pageRSSHub = {};
|
||||
window.websiteRSSHub = {};
|
||||
|
||||
function schedule(time = +new Date() + config.refreshTimeout * 1000) {
|
||||
chrome.alarms.create('refreshRules', {
|
||||
when: time,
|
||||
periodInMinutes: config.refreshTimeout / 60,
|
||||
});
|
||||
}
|
||||
|
||||
function initSchedule() {
|
||||
getRulesDate((lastDate) => {
|
||||
if (!lastDate || +new Date() - lastDate > config.refreshTimeout * 1000) {
|
||||
refreshRules();
|
||||
schedule();
|
||||
} else {
|
||||
schedule(lastDate + config.refreshTimeout * 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
chrome.storage.onChanged.addListener((result) => {
|
||||
if (result.config) {
|
||||
config = result.config.newValue;
|
||||
}
|
||||
if (result.rules) {
|
||||
getRules((rul) => {
|
||||
rules = rul;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
chrome.alarms.onAlarm.addListener((alarm) => {
|
||||
if (alarm.name === 'refreshRules') {
|
||||
refreshRules();
|
||||
}
|
||||
});
|
||||
|
||||
if ('idle' in chrome) {
|
||||
chrome.idle.onStateChanged.addListener((newState) => {
|
||||
if (newState === 'active') {
|
||||
initSchedule();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getConfig((conf) => {
|
||||
config = conf;
|
||||
|
||||
getRules((rul) => {
|
||||
rules = rul;
|
||||
initSchedule();
|
||||
});
|
||||
});
|
||||
|
||||
chrome.browserAction.setBadgeBackgroundColor({
|
||||
color: '#F62800',
|
||||
});
|
||||
|
||||
chrome.browserAction.setBadgeTextColor &&
|
||||
chrome.browserAction.setBadgeTextColor({
|
||||
color: '#fff',
|
||||
});
|
||||
|
||||
function setBadge(tabId) {
|
||||
chrome.browserAction.setBadgeText({
|
||||
text: config.notice.badge ? (window.pageRSS[tabId].length + (window.pageRSSHub[tabId] ? window.pageRSSHub[tabId].length : 0) || (window.websiteRSSHub[tabId] && window.websiteRSSHub[tabId].length ? ' ' : '')) + '' : '',
|
||||
tabId,
|
||||
});
|
||||
}
|
||||
|
||||
function getPageRSSHub(url, tabId, done) {
|
||||
chrome.tabs.sendMessage(
|
||||
tabId,
|
||||
{
|
||||
text: 'getHTML',
|
||||
},
|
||||
(html) => {
|
||||
commandSandbox(
|
||||
'getPageRSSHub',
|
||||
{
|
||||
url,
|
||||
html,
|
||||
rules,
|
||||
},
|
||||
done
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getWebsiteRSSHub(url, done) {
|
||||
commandSandbox(
|
||||
'getWebsiteRSSHub',
|
||||
{
|
||||
url,
|
||||
rules,
|
||||
},
|
||||
done
|
||||
);
|
||||
}
|
||||
|
||||
export function handleRSS(feeds, tabId, useCache) {
|
||||
if (useCache && window.pageRSS[tabId]) {
|
||||
setBadge(tabId);
|
||||
} else {
|
||||
chrome.tabs.get(tabId, (tab) => {
|
||||
feeds &&
|
||||
feeds.forEach((feed) => {
|
||||
feed.image = tab.favIconUrl || feed.image;
|
||||
});
|
||||
window.pageRSS[tabId] = (feeds && feeds.filter((feed) => !feed.uncertain)) || [];
|
||||
|
||||
getWebsiteRSSHub(tab.url, (feeds) => {
|
||||
window.websiteRSSHub[tabId] = feeds || [];
|
||||
setBadge(tabId);
|
||||
});
|
||||
|
||||
getPageRSSHub(tab.url, tabId, (feeds) => {
|
||||
window.pageRSSHub[tabId] = feeds || [];
|
||||
setBadge(tabId);
|
||||
});
|
||||
});
|
||||
|
||||
feeds &&
|
||||
feeds
|
||||
.filter((feed) => feed.uncertain)
|
||||
.forEach((feed) => {
|
||||
rssParser.parseURL(feed.url, (err, result) => {
|
||||
if (!err) {
|
||||
feed.title = result.title;
|
||||
window.pageRSS[tabId].push(feed);
|
||||
setBadge(tabId);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function removeRSS(tabId) {
|
||||
delete window.pageRSS[tabId];
|
||||
delete window.websiteRSSHub[tabId];
|
||||
delete window.pageRSSHub[tabId];
|
||||
}
|
||||
|
||||
export function addPageRSS(feed, tabId) {
|
||||
if (feed) {
|
||||
chrome.tabs.get(tabId, (tab) => {
|
||||
feed.image = tab.favIconUrl || feed.image;
|
||||
window.pageRSS[tabId].push(feed);
|
||||
setBadge(tabId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getAllRSS(tabId) {
|
||||
return {
|
||||
pageRSS: window.pageRSS[tabId] || {},
|
||||
websiteRSSHub: window.websiteRSSHub[tabId] || {},
|
||||
pageRSSHub: window.pageRSSHub[tabId] || {},
|
||||
};
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
export const defaultConfig = {
|
||||
rsshubDomain: 'https://rsshub.app',
|
||||
rsshubAccessControl: {
|
||||
enabled: false,
|
||||
accessKey: '',
|
||||
useCode: false,
|
||||
},
|
||||
notice: {
|
||||
badge: true,
|
||||
},
|
||||
submitto: {
|
||||
ttrss: false,
|
||||
ttrssDomain: '',
|
||||
checkchan: false,
|
||||
checkchanBase: '',
|
||||
miniflux: false,
|
||||
minifluxDomain: '',
|
||||
freshrss: false,
|
||||
freshrssDomain: '',
|
||||
nextcloudnews: false,
|
||||
nextcloudnewsDomain: '',
|
||||
feedly: true,
|
||||
inoreader: false,
|
||||
inoreaderDomain: 'https://www.inoreader.com',
|
||||
feedbin: false,
|
||||
feedbinDomain: 'https://feedbin.com',
|
||||
theoldreader: false,
|
||||
feedspub: false,
|
||||
bazqux: false,
|
||||
local: false,
|
||||
},
|
||||
refreshTimeout: 5 * 60 * 60,
|
||||
// typical UA:
|
||||
// Firefox: Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/99.0
|
||||
// Chromium/Chrome: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36
|
||||
// Some Chromium: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/80.0.3987.87 Chrome/80.0.3987.87 Safari/537.36
|
||||
// Safari: Mozilla/5.0 (Macintosh; Intel Mac OS X 12_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Safari/605.1.15
|
||||
// Edge: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/99.0.1150.36
|
||||
enableFullRemoteRules: !(navigator.userAgent.match(/firefox/i) || (navigator.userAgent.match(/safari/i) && !navigator.userAgent.match(/chrome/i))),
|
||||
};
|
||||
|
||||
export function getConfig(success) {
|
||||
if (chrome.storage) {
|
||||
chrome.storage.sync.get('config', (result) => {
|
||||
const config = Object.assign({}, defaultConfig, result.config);
|
||||
|
||||
if (!config.submitto.feedbinDomain) {
|
||||
config.submitto.feedbinDomain = defaultConfig.submitto.feedbinDomain;
|
||||
}
|
||||
if (!config.submitto.inoreaderDomain) {
|
||||
config.submitto.inoreaderDomain = defaultConfig.submitto.inoreaderDomain;
|
||||
}
|
||||
|
||||
success(config);
|
||||
});
|
||||
} else {
|
||||
success && success(defaultConfig);
|
||||
}
|
||||
}
|
||||
|
||||
export function saveConfig(config, success) {
|
||||
if (!config.rsshubDomain) {
|
||||
config.rsshubDomain = defaultConfig.rsshubDomain;
|
||||
}
|
||||
config.rsshubDomain = config.rsshubDomain.replace(/\/$/, '');
|
||||
if (config.rsshubDomain === defaultConfig.rsshubDomain) {
|
||||
config.rsshubAccessControl.enabled = defaultConfig.rsshubAccessControl.enabled;
|
||||
}
|
||||
if (chrome.storage) {
|
||||
chrome.storage.sync.set(
|
||||
{
|
||||
config,
|
||||
},
|
||||
() => {
|
||||
success && success();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { I18n } from 'i18n-js';
|
||||
import en from '../../translations/en.json';
|
||||
import es from '../../translations/es.json';
|
||||
import eu from '../../translations/eu.json';
|
||||
import pt from '../../translations/pt.json';
|
||||
import zh from '../../translations/zh.json';
|
||||
const i18n = new I18n({
|
||||
en,
|
||||
es,
|
||||
eu,
|
||||
pt,
|
||||
zh,
|
||||
});
|
||||
i18n.enableFallback = true;
|
||||
i18n.defaultLocale = 'en';
|
||||
i18n.locale = navigator.language;
|
||||
|
||||
export default i18n;
|
||||
@@ -1,51 +0,0 @@
|
||||
import { defaultConfig } from './config';
|
||||
|
||||
export function refreshRules(success) {
|
||||
const done = (response) => {
|
||||
response.text().then((text) => {
|
||||
chrome.storage.local.set({
|
||||
rules: text,
|
||||
rulesDate: +new Date(),
|
||||
});
|
||||
success && success();
|
||||
});
|
||||
};
|
||||
fetch(`https://rsshub.js.org/build/radar-rules.${defaultConfig.enableFullRemoteRules ? 'js' : 'json'}`)
|
||||
.then((response) => {
|
||||
done(response);
|
||||
})
|
||||
.catch(() => {
|
||||
fetch(`https://cdn.jsdelivr.net/gh/DIYgod/RSSHub@gh-pages/build/radar-rules.${defaultConfig.enableFullRemoteRules ? 'js' : 'json'}`).then((response) => {
|
||||
done(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function getRules(success) {
|
||||
chrome.storage.local.get('rules', (result) => {
|
||||
if (result && result.rules) {
|
||||
success(result.rules);
|
||||
} else {
|
||||
refreshRules(() => {
|
||||
getRules(success);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function getRulesDate(success) {
|
||||
chrome.storage.local.get('rulesDate', (result) => {
|
||||
if (result && result.rulesDate) {
|
||||
success(result.rulesDate);
|
||||
} else {
|
||||
success(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function updateRules(text, success) {
|
||||
chrome.storage.local.set({
|
||||
rules: text,
|
||||
});
|
||||
success && success();
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
export function secondToTime(second) {
|
||||
const hour = Math.floor(second / 3600);
|
||||
const min = Math.floor((second - hour * 3600) / 60);
|
||||
return `${hour ? hour + 'h ' : ''}${min}min `;
|
||||
}
|
||||
|
||||
export function secondToHoursMinutes(second) {
|
||||
const hours = Math.floor(second / 3600);
|
||||
const minutes = Math.floor((second - hours * 3600) / 60);
|
||||
return { hours, minutes };
|
||||
}
|
||||
|
||||
const iframe = document.querySelector('#sandbox');
|
||||
const returnResults = [];
|
||||
window.addEventListener('message', (event) => {
|
||||
returnResults.forEach((returnResult) => {
|
||||
returnResult(event);
|
||||
});
|
||||
});
|
||||
export function commandSandbox(command, data, callback) {
|
||||
if (data.rules && typeof data.rules === 'object') {
|
||||
try {
|
||||
callback(iframe.contentWindow[command](data));
|
||||
return;
|
||||
} catch (e) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
iframe.contentWindow.postMessage(
|
||||
{
|
||||
command: command,
|
||||
data: data,
|
||||
},
|
||||
'*'
|
||||
);
|
||||
|
||||
const myReturn = (event) => {
|
||||
if (event.data.origin.command === command && (!data.url || event.data.origin.data.url === data.url)) {
|
||||
returnResults.splice(returnResults.indexOf(myReturn), 1);
|
||||
if (event.data && event.data.result) {
|
||||
callback(event.data.result);
|
||||
}
|
||||
}
|
||||
};
|
||||
returnResults.push(myReturn);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { getPageRSS } from './utils';
|
||||
|
||||
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
if (msg.text === 'getPageRSS') {
|
||||
sendResponse(getPageRSS());
|
||||
} else if (msg.text === 'getHTML') {
|
||||
sendResponse(document.documentElement.innerHTML);
|
||||
}
|
||||
});
|
||||
|
||||
chrome.runtime.sendMessage(null, {
|
||||
text: 'setPageRSS',
|
||||
feeds: getPageRSS(),
|
||||
});
|
||||
@@ -1,120 +0,0 @@
|
||||
import RSSParser from 'rss-parser';
|
||||
const rssParser = new RSSParser();
|
||||
|
||||
let pageRSS = null;
|
||||
const defaultTitle =
|
||||
document.querySelector('title') &&
|
||||
document.querySelector('title').innerHTML &&
|
||||
document
|
||||
.querySelector('title')
|
||||
.innerHTML.replace(/<!\[CDATA\[(.*)]]>/, (match, p1) => p1)
|
||||
.trim();
|
||||
const image = (document.querySelector('link[rel~="icon"]') && handleUrl(document.querySelector('link[rel~="icon"]').getAttribute('href'))) || document.location.origin + '/favicon.ico';
|
||||
|
||||
function handleUrl(url) {
|
||||
return new URL(url, document.location.href).toString();
|
||||
}
|
||||
|
||||
export function getPageRSS() {
|
||||
if (!pageRSS) {
|
||||
pageRSS = [];
|
||||
const unique = {
|
||||
data: {},
|
||||
save: function (url) {
|
||||
this.data[url.replace(/^(https?:)?\/\//, '')] = 1;
|
||||
},
|
||||
check: function (url) {
|
||||
return this.data[url.replace(/^(https?:)?\/\//, '')];
|
||||
},
|
||||
};
|
||||
|
||||
// links
|
||||
const types = [
|
||||
'application/rss+xml',
|
||||
'application/atom+xml',
|
||||
'application/rdf+xml',
|
||||
'application/rss',
|
||||
'application/atom',
|
||||
'application/rdf',
|
||||
'text/rss+xml',
|
||||
'text/atom+xml',
|
||||
'text/rdf+xml',
|
||||
'text/rss',
|
||||
'text/atom',
|
||||
'text/rdf',
|
||||
'application/feed+json',
|
||||
];
|
||||
const links = document.querySelectorAll('link[type]');
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
if (links[i].hasAttribute('type') && types.indexOf(links[i].getAttribute('type')) !== -1) {
|
||||
const feed_url = links[i].getAttribute('href');
|
||||
|
||||
if (feed_url) {
|
||||
const feed = {
|
||||
url: handleUrl(feed_url),
|
||||
title: links[i].getAttribute('title') || defaultTitle,
|
||||
image,
|
||||
};
|
||||
if (!unique.check(feed.url)) {
|
||||
pageRSS.push(feed);
|
||||
unique.save(feed.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a
|
||||
const aEles = document.querySelectorAll('a');
|
||||
const check = /([^a-zA-Z]|^)rss([^a-zA-Z]|$)/i;
|
||||
for (let i = 0; i < aEles.length; i++) {
|
||||
if (aEles[i].hasAttribute('href')) {
|
||||
const href = aEles[i].getAttribute('href');
|
||||
|
||||
if (
|
||||
href.match(/\/(feed|rss|atom)(\.(xml|rss|atom))?\/?$/) ||
|
||||
(aEles[i].hasAttribute('title') && aEles[i].getAttribute('title').match(check)) ||
|
||||
(aEles[i].hasAttribute('class') && aEles[i].getAttribute('class').match(check)) ||
|
||||
(aEles[i].innerText && aEles[i].innerText.match(check))
|
||||
) {
|
||||
const feed = {
|
||||
url: handleUrl(href),
|
||||
title: aEles[i].innerText || aEles[i].getAttribute('title') || defaultTitle,
|
||||
image,
|
||||
uncertain: 1,
|
||||
};
|
||||
if (!unique.check(feed.url)) {
|
||||
pageRSS.push(feed);
|
||||
unique.save(feed.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// whole page
|
||||
if (!unique.check(document.location.href)) {
|
||||
let html;
|
||||
if (document.body && document.body.childNodes && document.body.childNodes.length === 1 && document.body.childNodes[0].tagName && document.body.childNodes[0].tagName.toLowerCase()) {
|
||||
html = document.body.childNodes[0].innerText;
|
||||
} else if (document.querySelector('#webkit-xml-viewer-source-xml')) {
|
||||
html = document.querySelector('#webkit-xml-viewer-source-xml').innerHTML;
|
||||
}
|
||||
|
||||
if (html) {
|
||||
rssParser.parseString(html, (err, result) => {
|
||||
if (!err) {
|
||||
chrome.runtime.sendMessage(null, {
|
||||
text: 'addPageRSS',
|
||||
feed: {
|
||||
url: document.location.href,
|
||||
title: result.title,
|
||||
image,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
unique.save(document.location.href);
|
||||
}
|
||||
return pageRSS;
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<el-container class="container">
|
||||
<el-aside width="200px">
|
||||
<el-menu
|
||||
class="menu"
|
||||
:default-active="this.$route.path"
|
||||
@select="handleSelect">
|
||||
<el-header
|
||||
class="header"
|
||||
height="80px">RSSHub Radar</el-header>
|
||||
<el-menu-item index="/setting">
|
||||
<i class="el-icon-setting"></i>
|
||||
<span slot="title">{{ $i18n.t('settings') }}</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/list">
|
||||
<i class="el-icon-magic-stick"></i>
|
||||
<span slot="title">{{ $i18n.t('list of rules') }}</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/about">
|
||||
<i class="el-icon-coordinate"></i>
|
||||
<span slot="title">{{ $i18n.t('about') }}</span>
|
||||
</el-menu-item>
|
||||
<el-footer class="footer">{{ $i18n.t('version')}} v{{ version }}<br>Made with <i style="color:#d43f57">♥</i> by <a target="_blank" href="https://diygod.me">DIYgod</a></el-footer>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-container class="sub-container">
|
||||
<!-- <el-main><router-view></router-view></el-main> -->
|
||||
<router-view></router-view>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'app',
|
||||
data: () => ({
|
||||
version: VERSION,
|
||||
}),
|
||||
methods: {
|
||||
handleSelect(key, keyPath) {
|
||||
this.$router.push(key);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@color-primary: #f5712c;
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#app {
|
||||
font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sub-container {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.menu {
|
||||
height: 100%;
|
||||
|
||||
.el-menu-item {
|
||||
&:focus {
|
||||
background-color: transparent;
|
||||
}
|
||||
&:hover {
|
||||
background-color: #fef1ea;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
color: @color-primary;
|
||||
line-height: 80px;
|
||||
font-size: 21px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
line-height: 60px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
line-height: 25px;
|
||||
|
||||
a {
|
||||
color: @color-primary;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.el-menu-item {
|
||||
i,
|
||||
span {
|
||||
transition: color .3s;
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
color: #303133;
|
||||
|
||||
i,
|
||||
span {
|
||||
color: #f5712c;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,52 +0,0 @@
|
||||
import '../../css/options.scss';
|
||||
import Vue from 'vue';
|
||||
import VueRouter from 'vue-router';
|
||||
import App from './App.vue';
|
||||
import Setting from './views/Setting.vue';
|
||||
import List from './views/List.vue';
|
||||
import About from './views/About.vue';
|
||||
import i18n from '../common/i18n';
|
||||
import { Container, Menu, MenuItem, Aside, Header, Main, Footer, Input, Checkbox, Message, Loading, Collapse, CollapseItem, Button, Progress, Tooltip } from 'element-ui';
|
||||
|
||||
// import translations from "../../translations/translations.json";
|
||||
// const i18n = new I18n(translations);
|
||||
// i18n.enableFallback = true;
|
||||
// i18n.defaultLocale = "zh";
|
||||
// i18n.locale = navigator.language;
|
||||
|
||||
Vue.use(VueRouter);
|
||||
Vue.use(Container);
|
||||
Vue.use(Menu);
|
||||
Vue.use(MenuItem);
|
||||
Vue.use(Aside);
|
||||
Vue.use(Header);
|
||||
Vue.use(Main);
|
||||
Vue.use(Footer);
|
||||
Vue.use(Input);
|
||||
Vue.use(Checkbox);
|
||||
Vue.use(Loading.directive);
|
||||
Vue.use(Collapse);
|
||||
Vue.use(CollapseItem);
|
||||
Vue.use(Button);
|
||||
Vue.use(Progress);
|
||||
Vue.use(Tooltip);
|
||||
|
||||
Vue.prototype.$loading = Loading.service;
|
||||
Vue.prototype.$message = Message;
|
||||
Vue.prototype.$i18n = i18n;
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
const routes = [
|
||||
{ path: '/', redirect: '/setting' },
|
||||
{ path: '/setting', component: Setting },
|
||||
{ path: '/list', component: List },
|
||||
{ path: '/about', component: About },
|
||||
];
|
||||
const router = new VueRouter({
|
||||
routes,
|
||||
});
|
||||
|
||||
new Vue({
|
||||
render: (h) => h(App),
|
||||
router,
|
||||
}).$mount('#app');
|
||||
@@ -1,62 +0,0 @@
|
||||
<template>
|
||||
<div class="about">
|
||||
<el-main>
|
||||
<div class="title">{{$i18n.t('about')}}</div>
|
||||
<div class="content">
|
||||
<div class="tip">
|
||||
<p v-html="$i18n.t('rsshub radar info')"></p>
|
||||
<p><i class="el-icon-trophy"></i> <span v-html="$i18n.t('sponsored development')"></span></p>
|
||||
<p> </p>
|
||||
<p>{{$i18n.t('update log')}}: <a target="_blank" href="https://github.com/DIYgod/RSSHub-Radar/releases">https://github.com/DIYgod/RSSHub-Radar/releases</a></p>
|
||||
<p>{{$i18n.t('question feedback')}}: <a target="_blank" href="https://github.com/DIYgod/RSSHub-radar/issues">https://github.com/DIYgod/RSSHub-radar/issues</a></p>
|
||||
<p>GitHub: <a target="_blank" href="https://github.com/DIYgod/RSSHub-Radar">https://github.com/DIYgod/RSSHub-Radar</a></p>
|
||||
<p v-html="$i18n.t('rsshub documentation')"></p>
|
||||
<p> </p>
|
||||
<p><b>{{$i18n.t('everything is possible with rss')}}</b></p>
|
||||
<p><b>Made with <i style="color:#d43f57">♥</i> by <a target="_blank" href="https://diygod.me">DIYgod</a></b></p>
|
||||
</div>
|
||||
</div>
|
||||
</el-main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'About',
|
||||
data: () => ({
|
||||
}),
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #f5712c;
|
||||
}
|
||||
|
||||
.about {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 40px 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #e6e6e6;
|
||||
padding-bottom: 10px;
|
||||
color: #f5712c;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 14px;
|
||||
margin: 20px 0;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 20px;
|
||||
color: #222;
|
||||
}
|
||||
</style>
|
||||
@@ -1,140 +0,0 @@
|
||||
<template>
|
||||
<div class="list">
|
||||
<el-main>
|
||||
<div class="title">{{ $i18n.t('rules') }}</div>
|
||||
<div class="tip">
|
||||
<p v-html="$i18n.t('for more rules join us')"></p>
|
||||
<p>{{ $i18n.t('updated time ago', {hours: hours, minutes: minutes})}}</p>
|
||||
</div>
|
||||
<div class="content" v-loading="loading">
|
||||
<el-collapse accordion>
|
||||
<el-collapse-item v-for="(rule, domain) in rules" :key="domain" :title="rule._name + ' - ' + domain">
|
||||
<div v-for="(subrule, subdomain) in rule" v-if="subdomain[0] !== '_'" :key="subdomain">
|
||||
<p v-for="subsubrule in subrule" :key="subsubrule.title">
|
||||
<a target="_blank" :href="subsubrule.docs">{{ subsubrule.title }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<div class="debug">
|
||||
<div class="tip" v-if="defaultConfig.enableFullRemoteRules">
|
||||
<p>This area is used for debugging rules in development</p>
|
||||
<p>Edited content may be overwritten by automatically updated rules at any time, please ensure that there is a local backup</p>
|
||||
<p>Use Settings - Update Now to immediately restore remote rules</p>
|
||||
</div>
|
||||
<div class="tip" v-if="!defaultConfig.enableFullRemoteRules">
|
||||
<p>This area is used for debugging rules in development</p>
|
||||
<p>Remote updates and debug function is not available due to browser limitations</p>
|
||||
</div>
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="100"
|
||||
v-model="rulesText"
|
||||
@change="updateRules"
|
||||
:disabled="!defaultConfig.enableFullRemoteRules"
|
||||
>
|
||||
</el-input>
|
||||
</div>
|
||||
</div>
|
||||
</el-main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getRules, getRulesDate, updateRules } from '../../common/rules';
|
||||
import { secondToHoursMinutes, commandSandbox } from '../../common/utils';
|
||||
import { defaultConfig } from '../../common/config';
|
||||
|
||||
export default {
|
||||
name: 'List',
|
||||
data: () => ({
|
||||
loading: true,
|
||||
rules: {},
|
||||
hours: '',
|
||||
minutes: '',
|
||||
rulesText: '',
|
||||
defaultConfig,
|
||||
}),
|
||||
created() {
|
||||
getRulesDate((date) => {
|
||||
let second = (+new Date - +date) / 1000;
|
||||
const {hours, minutes} = secondToHoursMinutes(second)
|
||||
this.hours = hours;
|
||||
this.minutes = minutes;
|
||||
this.refreshTime();
|
||||
});
|
||||
getRules((rules) => {
|
||||
if (typeof rules === 'string') {
|
||||
this.rulesText = rules;
|
||||
commandSandbox('getList', {
|
||||
rules,
|
||||
}, (rules) => {
|
||||
this.rules = rules;
|
||||
this.loading = false;
|
||||
});
|
||||
} else {
|
||||
this.rulesText = JSON.stringify(rules, null, 4);
|
||||
this.rules = rules;
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
refreshTime() {
|
||||
getRulesDate((date) => {
|
||||
const {hours, minutes} = secondToHoursMinutes((+new Date - +date) / 1000)
|
||||
this.hours = hours;
|
||||
this.minutes = minutes;
|
||||
setTimeout(() => {
|
||||
this.refreshTime();
|
||||
}, 1000);
|
||||
});
|
||||
},
|
||||
updateRules() {
|
||||
updateRules(this.rulesText, () => {
|
||||
this.$message({
|
||||
message: this.$i18n.t('successfully saved'),
|
||||
type: 'success'
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #f5712c;
|
||||
}
|
||||
|
||||
.list {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 40px 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #e6e6e6;
|
||||
padding-bottom: 10px;
|
||||
color: #f5712c;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 14px;
|
||||
margin: 20px 0;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 20px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.debug {
|
||||
margin: 200px 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,235 +0,0 @@
|
||||
<template>
|
||||
<div class="setting">
|
||||
<div class="title">{{ $i18n.t('settings') }}</div>
|
||||
<div class="content" v-loading="loading">
|
||||
<div v-if="!loading">
|
||||
<div class="subtitle">{{ $i18n.t('general') }}</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-name">{{ $i18n.t('custom rsshub domain') }}</div>
|
||||
<div class="setting-input">
|
||||
<el-input @change="saveConfig" v-model="config.rsshubDomain" :placeholder="$i18n.t('enter rsshub domain')"></el-input>
|
||||
</div>
|
||||
<template v-if="config.rsshubDomain !== defaultConfig.rsshubDomain">
|
||||
<div class="setting-name">{{ $i18n.t('access key') }}<a target="_blank" href="https://docs.rsshub.app/install/#fang-wen-kong-zhi-pei-zhi"><el-tooltip class="item" effect="dark" :content="$i18n.t('configuration required if access keys enabled')" placement="top"><i class="el-icon-info"></i></el-tooltip></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.rsshubAccessControl.enabled">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
<el-input @change="saveConfig" style="margin-left: 20px;" v-if="config.rsshubAccessControl.enabled" v-model="config.rsshubAccessControl.accessKey" :placeholder="$i18n.t('required access key')"></el-input>
|
||||
<el-checkbox @change="saveConfig" style="margin-left: 20px;" v-if="config.rsshubAccessControl.enabled" v-model="config.rsshubAccessControl.useCode">{{ $i18n.t('generate access code') }}</el-checkbox>
|
||||
</div>
|
||||
</template>
|
||||
<div class="setting-name" v-if="isChrome">{{ $i18n.t('hot key') }}</div>
|
||||
<div class="setting-input" v-if="isChrome">
|
||||
<el-button size="medium" @click="toHotkey">{{ $i18n.t('click to set') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="subtitle">{{ $i18n.t('rules update') }}</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-name">{{ $i18n.t('i will update automatically and you can') }}</div>
|
||||
<div class="setting-input">
|
||||
<el-button style="" size="medium" @click="refreshRu" :disabled="refreshDisabled">{{ refreshDisabled ? $i18n.t('updating') : $i18n.t('update now') }}</el-button><el-progress :text-inside="true" :stroke-width="20" :percentage="percentage"></el-progress><span class="time">{{ time }} {{ $i18n.t('before update') }}, {{ leftTime }} {{ $i18n.t('after automatic update') }}</span>
|
||||
</div>
|
||||
<div class="setting-name" v-if="!defaultConfig.enableFullRemoteRules">{{ $i18n.t('full remote updates are disabled due to browser limitations') }}</div>
|
||||
</div>
|
||||
<div class="subtitle">{{ $i18n.t('one-click subscription') }}</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-name">Check酱<a target="_blank" href="https://ckc.ftqq.com"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.checkchan">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
<el-input @change="saveConfig" style="margin-left: 20px;" v-if="config.submitto.checkchan" v-model="config.submitto.checkchanBase" :placeholder="$i18n.t('required extension base URI', {service: 'CheckChan'})"></el-input>
|
||||
</div>
|
||||
<div class="setting-name">Tiny Tiny RSS <a target="_blank" href="https://ttrss.henry.wang/zh/"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.ttrss">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
<el-input @change="saveConfig" style="margin-left: 20px;" v-if="config.submitto.ttrss" v-model="config.submitto.ttrssDomain" :placeholder="$i18n.t('required address', {service: 'Tiny Tiny RSS'})"></el-input>
|
||||
</div>
|
||||
<div class="setting-name">Miniflux <a target="_blank" href="https://miniflux.app"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.miniflux">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
<el-input @change="saveConfig" style="margin-left: 20px;" v-if="config.submitto.miniflux" v-model="config.submitto.minifluxDomain" :placeholder="$i18n.t('required address', {service: 'Miniflux'})"></el-input>
|
||||
</div>
|
||||
<div class="setting-name">FreshRSS <a target="_blank" href="https://freshrss.org"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.freshrss">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
<el-input @change="saveConfig" style="margin-left: 20px;" v-if="config.submitto.freshrss" v-model="config.submitto.freshrssDomain" :placeholder="$i18n.t('required address', {service: 'FreshRSS'})"></el-input>
|
||||
</div>
|
||||
<div class="setting-name">Nextcloud News <a target="_blank" href="https://apps.nextcloud.com/apps/news"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.nextcloudnews">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
<el-input @change="saveConfig" style="margin-left: 20px;" v-if="config.submitto.nextcloudnews" v-model="config.submitto.nextcloudnewsDomain" :placeholder="$i18n.t('required address', {service: 'Nextcloud'})"></el-input>
|
||||
</div>
|
||||
<div class="setting-name">Feedly <a target="_blank" href="https://feedly.com/"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.feedly">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
</div>
|
||||
<div class="setting-name">Inoreader <a target="_blank" href="https://www.inoreader.com/"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.inoreader">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
<el-input @change="saveConfig" style="margin-left: 20px;" v-if="config.submitto.inoreader" v-model="config.submitto.inoreaderDomain" :placeholder="$i18n.t('required address', {service: 'Inoreader'})"></el-input>
|
||||
</div>
|
||||
<div class="setting-name">Feedbin <a target="_blank" href="https://feedbin.com/"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.feedbin">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
<el-input @change="saveConfig" style="margin-left: 20px;" v-if="config.submitto.feedbin" v-model="config.submitto.feedbinDomain" :placeholder="$i18n.t('required address', {service: 'Feedbin'})"></el-input>
|
||||
</div>
|
||||
<div class="setting-name">The Old Reader <a target="_blank" href="https://theoldreader.com/"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.theoldreader">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
</div>
|
||||
<div class="setting-name">Feeds.Pub <a target="_blank" href="https://feeds.pub/"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.feedspub">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
</div>
|
||||
<div class="setting-name">BazQux Reader <a target="_blank" href="https://bazqux.com/"><i class="el-icon-info"></i></a></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.bazqux">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
</div>
|
||||
<div class="setting-name">{{ $i18n.t('local reader') }} <el-tooltip class="item" effect="dark" :content="$i18n.t('requires reader support')" placement="top"><i class="el-icon-info"></i></el-tooltip></div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.submitto.local">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="subtitle">{{ $i18n.t('notifications and reminders') }}</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-name">{{ $i18n.t('show corner badge') }}</div>
|
||||
<div class="setting-input">
|
||||
<el-checkbox @change="saveConfig" v-model="config.notice.badge">{{ $i18n.t('enable') }}</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getRulesDate, refreshRules } from '../../common/rules';
|
||||
import { defaultConfig, getConfig, saveConfig } from '../../common/config';
|
||||
import { secondToTime } from '../../common/utils';
|
||||
|
||||
export default {
|
||||
name: 'Setting',
|
||||
data: () => ({
|
||||
loading: true,
|
||||
defaultConfig,
|
||||
config: defaultConfig,
|
||||
time: '',
|
||||
leftTime: '',
|
||||
second: 0,
|
||||
refreshDisabled: false,
|
||||
isChrome: navigator.userAgent.indexOf('Chrome') !== -1,
|
||||
}),
|
||||
computed: {
|
||||
percentage: function () {
|
||||
return (this.second / this.config.refreshTimeout * 100).toFixed(2);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
getConfig((config) => {
|
||||
this.config = config;
|
||||
this.loading = false;
|
||||
|
||||
this.refreshTime();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
saveConfig() {
|
||||
saveConfig(this.config, () => {
|
||||
this.$message({
|
||||
message: this.$i18n.t('successfully saved'),
|
||||
type: 'success'
|
||||
});
|
||||
});
|
||||
},
|
||||
toHotkey() {
|
||||
chrome.tabs.create({
|
||||
url: 'chrome://extensions/shortcuts'
|
||||
});
|
||||
},
|
||||
refreshRu() {
|
||||
this.refreshDisabled = true;
|
||||
refreshRules(() => {
|
||||
this.second = 0;
|
||||
this.time = secondToTime(this.second);
|
||||
this.leftTime = secondToTime(this.config.refreshTimeout - this.second);
|
||||
this.refreshDisabled = false;
|
||||
});
|
||||
},
|
||||
refreshTime() {
|
||||
getRulesDate((date) => {
|
||||
this.second = (+new Date - +date) / 1000;
|
||||
this.time = secondToTime(this.second);
|
||||
this.leftTime = secondToTime(this.config.refreshTimeout - this.second);
|
||||
setTimeout(() => {
|
||||
this.refreshTime();
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.setting {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 40px 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #e6e6e6;
|
||||
padding-bottom: 10px;
|
||||
color: #f5712c;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 30px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin: 30px 0 15px;
|
||||
}
|
||||
|
||||
.setting-name {
|
||||
font-size: 15px;
|
||||
margin: 15px 0 5px;
|
||||
}
|
||||
|
||||
.setting-input {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.el-button:focus {
|
||||
color: #606266;
|
||||
background: #fff;
|
||||
border: 1px solid #dcdfe6;
|
||||
}
|
||||
|
||||
.el-button:hover {
|
||||
color: #f5712c;
|
||||
border-color: #fcd4c0;
|
||||
background-color: #fef1ea;
|
||||
}
|
||||
|
||||
.el-icon-info {
|
||||
color: #777;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.el-progress {
|
||||
width: 170px;
|
||||
margin: 0 20px;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: #606266;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,145 +0,0 @@
|
||||
import '../../css/popup.less';
|
||||
import ClipboardJS from 'clipboard';
|
||||
import { getConfig } from '../common/config';
|
||||
import i18n from '../common/i18n';
|
||||
import settingIcon from '../../svg/setting.svg';
|
||||
import aboutIcon from '../../svg/about.svg';
|
||||
import MD5 from 'md5.js';
|
||||
|
||||
let config;
|
||||
let favicon;
|
||||
let title;
|
||||
|
||||
function generateList(type, list) {
|
||||
let result = '';
|
||||
if (list && list.length) {
|
||||
list.forEach((item) => {
|
||||
const replaced_url = item.url.replace('{rsshubDomain}', config.rsshubDomain);
|
||||
const url = encodeURI(
|
||||
type !== 'page-rsshub' || !config.rsshubAccessControl.enabled
|
||||
? replaced_url
|
||||
: config.rsshubAccessControl.useCode
|
||||
? `${replaced_url}?code=${new MD5().update(item.path + config.rsshubAccessControl.accessKey).digest('hex')}`
|
||||
: `${replaced_url}?key=${config.rsshubAccessControl.accessKey}`
|
||||
);
|
||||
result += `
|
||||
<li class="rss-item">
|
||||
<img class="rss-image" src="${item.image || './rsshub.png'}">
|
||||
<a href="${url}" class="rss-info">
|
||||
<div class="rss-title">${item.title}</div>
|
||||
<div class="rss-url">${url.replace('https://', '').replace('http://', '')}</div>
|
||||
</a>
|
||||
${
|
||||
item.isDocs
|
||||
? `<a href="${url}" class="rss-action">${i18n.t('documentation')}</a>`
|
||||
: `<div class="rss-action rss-copy" data-clipboard-text="${url}">${i18n.t('copy')}</div>
|
||||
${
|
||||
config.submitto.checkchan && config.submitto.checkchanBase
|
||||
? `<a href="${config.submitto.checkchanBase.replace(/\/$/, '')}/index.html#/check/add?title=${encodeURI(title)}&url=${encodeURI(url)}&type=rss&icon=${encodeURI(
|
||||
favicon
|
||||
)}" class="rss-action rss-submitto-checkchan">${i18n.t('subscribe to')} CheckChan</a>`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
config.submitto.ttrss && config.submitto.ttrssDomain
|
||||
? `<a href="${config.submitto.ttrssDomain.replace(/\/$/, '')}/public.php?op=bookmarklets--subscribe&feed_url=${encodeURI(url)}" class="rss-action rss-submitto-ttrss">${i18n.t('subscribe to')} TTRSS</a>`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
config.submitto.miniflux && config.submitto.minifluxDomain
|
||||
? `<a href="${config.submitto.minifluxDomain.replace(/\/$/, '')}/bookmarklet?uri=${encodeURI(url)}" class="rss-action rss-submitto-miniflux">${i18n.t('subscribe to')} Miniflux</a>`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
config.submitto.freshrss && config.submitto.freshrssDomain
|
||||
? `<a href="${config.submitto.freshrssDomain.replace(/\/$/, '')}/i/?c=feed&a=add&url_rss=${encodeURI(url)}" class="rss-action rss-submitto-freshrss">${i18n.t('subscribe to')} FreshRSS</a>`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
config.submitto.nextcloudnews && config.submitto.nextcloudnewsDomain
|
||||
? `<a href="${config.submitto.nextcloudnewsDomain.replace(/\/$/, '')}/?subscribe_to=${encodeURI(url)}" class="rss-action rss-submitto-nextcloudnews">${i18n.t('subscribe to')} Nextcloud News</a>`
|
||||
: ''
|
||||
}
|
||||
${config.submitto.feedly ? `<a href="https://feedly.com/i/subscription/feed/${encodeURI(url)}" class="rss-action rss-submitto-feedly">${i18n.t('subscribe to')} Feedly</a>` : ''}
|
||||
${
|
||||
config.submitto.inoreader && config.submitto.inoreaderDomain
|
||||
? `<a href="${config.submitto.inoreaderDomain.replace(/\/$/, '')}/?add_feed=${encodeURI(url)}" class="rss-action rss-submitto-inoreader">${i18n.t('subscribe to')} Inoreader</a>`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
config.submitto.feedbin && config.submitto.feedbinDomain
|
||||
? `<a href="${config.submitto.feedbinDomain.replace(/\/$/, '')}/?subscribe=${encodeURI(url)}" class="rss-action rss-submitto-feedbin">${i18n.t('subscribe to')} Feedbin</a>`
|
||||
: ''
|
||||
}
|
||||
${config.submitto.theoldreader ? `<a href="https://theoldreader.com/feeds/subscribe?url=${encodeURI(url)}" class="rss-action rss-submitto-theoldreader">${i18n.t('subscribe to')} The Old Reader</a>` : ''}
|
||||
${config.submitto.feedspub ? `<a href="https://feeds.pub/feed/${encodeURIComponent(url)}" class="rss-action rss-submitto-feedspub">${i18n.t('subscribe to')} Feeds.Pub</a>` : ''}
|
||||
${config.submitto.bazqux ? `<a href="https://bazqux.com/add?url=${encodeURIComponent(url)}" class="rss-action rss-submitto-bazqux">${i18n.t('subscribe to')} BazQux Reader</a>` : ''}
|
||||
${config.submitto.local ? `<a href="feed://${url}" class="rss-action rss-submitto-local">${i18n.t('subscribe to local reader')}</a>` : ''}`
|
||||
}
|
||||
</li>
|
||||
`;
|
||||
});
|
||||
document.querySelector(`.${type} ul`).innerHTML = result;
|
||||
document.querySelector(`.${type}`).style.display = 'block';
|
||||
document.body.classList.add('something');
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector('.icons-setting').innerHTML = settingIcon;
|
||||
document.querySelector('.icons-about').innerHTML = aboutIcon;
|
||||
|
||||
const translatableNodes = document.querySelectorAll('[data-i18n]');
|
||||
[...translatableNodes].forEach((element) => {
|
||||
element.innerHTML = i18n.t(element.innerHTML);
|
||||
});
|
||||
|
||||
chrome.tabs.query(
|
||||
{
|
||||
active: true,
|
||||
currentWindow: true,
|
||||
},
|
||||
(tabs) => {
|
||||
const tabId = tabs[0].id;
|
||||
title = tabs[0].title || '';
|
||||
favicon = tabs[0].favIconUrl || '/favicon.ico';
|
||||
getConfig((conf) => {
|
||||
config = conf;
|
||||
chrome.runtime.sendMessage(
|
||||
null,
|
||||
{
|
||||
text: 'getAllRSS',
|
||||
tabId: tabId,
|
||||
},
|
||||
(feeds) => {
|
||||
generateList('page-rss', feeds.pageRSS);
|
||||
generateList('page-rsshub', feeds.pageRSSHub);
|
||||
generateList('website-rsshub', feeds.websiteRSSHub);
|
||||
|
||||
const clipboard = new ClipboardJS('.rss-copy');
|
||||
clipboard.on('success', function (e) {
|
||||
e.trigger.innerHTML = i18n.t('copied');
|
||||
setTimeout(() => {
|
||||
e.trigger.innerHTML = i18n.t('copy');
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
document.querySelectorAll('.rss-image').forEach((ele) => {
|
||||
ele.addEventListener('error', function () {
|
||||
this.setAttribute('src', './rsshub.png');
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('a').forEach((ele) => {
|
||||
ele.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
chrome.tabs.create({
|
||||
url: ele.getAttribute('href'),
|
||||
});
|
||||
window.close();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,38 +0,0 @@
|
||||
import { getPageRSSHub, getWebsiteRSSHub, getList } from './utils';
|
||||
|
||||
window.getPageRSSHub = getPageRSSHub;
|
||||
window.getWebsiteRSSHub = getWebsiteRSSHub;
|
||||
window.getList = getList;
|
||||
|
||||
window.addEventListener('message', function (event) {
|
||||
const command = event.data.command;
|
||||
switch (command) {
|
||||
case 'getPageRSSHub':
|
||||
event.source.postMessage(
|
||||
{
|
||||
origin: event.data,
|
||||
result: getPageRSSHub(event.data.data),
|
||||
},
|
||||
event.origin
|
||||
);
|
||||
break;
|
||||
case 'getWebsiteRSSHub':
|
||||
event.source.postMessage(
|
||||
{
|
||||
origin: event.data,
|
||||
result: getWebsiteRSSHub(event.data.data),
|
||||
},
|
||||
event.origin
|
||||
);
|
||||
break;
|
||||
case 'getList':
|
||||
event.source.postMessage(
|
||||
{
|
||||
origin: event.data,
|
||||
result: getList(event.data.data),
|
||||
},
|
||||
event.origin
|
||||
);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -1,244 +0,0 @@
|
||||
import psl from 'psl';
|
||||
import RouteRecognizer from 'route-recognizer';
|
||||
import _ from 'lodash';
|
||||
import { defaultRules } from '../common/radar-rules';
|
||||
import { defaultConfig } from '../common/config';
|
||||
|
||||
function ruleHandler(rule, params, url, html, success, fail) {
|
||||
const run = () => {
|
||||
let resultWithParams;
|
||||
if (typeof rule.target === 'function') {
|
||||
const parser = new DOMParser();
|
||||
const document = parser.parseFromString(html, 'text/html');
|
||||
try {
|
||||
resultWithParams = rule.target(params, url, document);
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
resultWithParams = '';
|
||||
}
|
||||
} else if (typeof rule.target === 'string') {
|
||||
resultWithParams = rule.target;
|
||||
}
|
||||
|
||||
if (resultWithParams) {
|
||||
// if no :param in resultWithParams, requiredParams will be null
|
||||
// in that case, just skip the following steps and return resultWithParams
|
||||
const requiredParams = resultWithParams.match(/\/:\w+\??(?=\/|$)/g)?.map((param) => ({
|
||||
name: param.slice(2).replace(/\?$/, ''),
|
||||
optional: param.endsWith('?'),
|
||||
}));
|
||||
if (!requiredParams) {
|
||||
return resultWithParams;
|
||||
}
|
||||
for (const param of requiredParams) {
|
||||
if (params[param.name]) {
|
||||
// successfully matched
|
||||
const regex = new RegExp(`/:${param.name}\\??(?=/|$)`);
|
||||
resultWithParams = resultWithParams.replace(regex, `/${params[param.name]}`);
|
||||
} else if (param.optional) {
|
||||
// missing optional parameter, drop all following parameters, otherwise the route will be invalid
|
||||
const regex = new RegExp(`/:${param.name}\\?(/.*)?$`);
|
||||
resultWithParams = resultWithParams.replace(regex, '');
|
||||
break;
|
||||
} else {
|
||||
// missing necessary parameter, fail
|
||||
resultWithParams = '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
// bypassing double-check since `:` maybe a part of parameter value
|
||||
// if (resultWithParams && resultWithParams.includes(':')) {
|
||||
// // double-check
|
||||
// resultWithParams = '';
|
||||
// }
|
||||
}
|
||||
return resultWithParams;
|
||||
};
|
||||
const resultWithParams = run();
|
||||
if (resultWithParams && (!rule.verification || rule.verification(params))) {
|
||||
success(resultWithParams);
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
function formatBlank(str1, str2) {
|
||||
if (str1 && str2) {
|
||||
return str1 + (str1[str1.length - 1].match(/[a-zA-Z0-9]/) || str2[0].match(/[a-zA-Z0-9]/) ? ' ' : '') + str2;
|
||||
} else {
|
||||
return (str1 || '') + (str2 || '');
|
||||
}
|
||||
}
|
||||
|
||||
function parseRules(rules) {
|
||||
let incomeRules = rules;
|
||||
if (typeof rules === 'string') {
|
||||
if (defaultConfig.enableFullRemoteRules) {
|
||||
incomeRules = window['lave'.split('').reverse().join('')](rules);
|
||||
} else {
|
||||
incomeRules = JSON.parse(rules);
|
||||
}
|
||||
}
|
||||
return _.mergeWith(defaultRules, incomeRules, (objValue, srcValue) => {
|
||||
if (_.isFunction(srcValue)) {
|
||||
return srcValue;
|
||||
} else if (_.isFunction(objValue)) {
|
||||
return objValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function getPageRSSHub(data) {
|
||||
const { url, html } = data;
|
||||
const rules = parseRules(data.rules);
|
||||
|
||||
let parsedDomain;
|
||||
try {
|
||||
parsedDomain = psl.parse(new URL(url).hostname);
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
if (parsedDomain && parsedDomain.domain) {
|
||||
const subdomain = parsedDomain.subdomain;
|
||||
const domain = parsedDomain.domain;
|
||||
if (rules[domain]) {
|
||||
let rule = rules[domain][subdomain || '.'];
|
||||
if (!rule) {
|
||||
if (subdomain === 'www') {
|
||||
rule = rules[domain]['.'];
|
||||
} else if (!subdomain) {
|
||||
rule = rules[domain].www;
|
||||
}
|
||||
}
|
||||
if (rule) {
|
||||
const recognized = [];
|
||||
rule.forEach((ru, index) => {
|
||||
const oriSources = Object.prototype.toString.call(ru.source) === '[object Array]' ? ru.source : typeof ru.source === 'string' ? [ru.source] : [];
|
||||
let sources = [];
|
||||
// route-recognizer do not support optional segments or partial matching
|
||||
// thus, we need to manually handle it
|
||||
// allowing partial matching is necessary, since many rule authors did not mark optional segments
|
||||
oriSources.forEach((source) => {
|
||||
// trimming `?` is necessary, since route-recognizer considers it as a part of segment
|
||||
source = source.replace(/(\/:\w+)\?(?=\/|$)/g, '$1');
|
||||
sources.push(source);
|
||||
let tailMatch;
|
||||
do {
|
||||
tailMatch = source.match(/\/:\w+$/);
|
||||
if (tailMatch) {
|
||||
const tail = tailMatch[0];
|
||||
source = source.slice(0, source.length - tail.length);
|
||||
sources.push(source);
|
||||
}
|
||||
} while (tailMatch);
|
||||
});
|
||||
// deduplicate (some rule authors may already have done similar job)
|
||||
sources = sources.filter((item, index) => sources.indexOf(item) === index);
|
||||
// match!
|
||||
sources.forEach((source) => {
|
||||
const router = new RouteRecognizer();
|
||||
router.add([
|
||||
{
|
||||
path: source,
|
||||
handler: index,
|
||||
},
|
||||
]);
|
||||
const result = router.recognize(new URL(url).pathname.replace(/\/$/, ''));
|
||||
if (result && result[0]) {
|
||||
recognized.push(result[0]);
|
||||
}
|
||||
});
|
||||
});
|
||||
const result = [];
|
||||
Promise.all(
|
||||
recognized.map(
|
||||
(recog) =>
|
||||
new Promise((resolve) => {
|
||||
ruleHandler(
|
||||
rule[recog.handler],
|
||||
recog.params,
|
||||
url,
|
||||
html,
|
||||
(parsed) => {
|
||||
if (parsed) {
|
||||
result.push({
|
||||
title: formatBlank(rules[domain]._name ? '当前' : '', rule[recog.handler].title),
|
||||
url: '{rsshubDomain}' + parsed,
|
||||
path: parsed,
|
||||
});
|
||||
} else {
|
||||
result.push({
|
||||
title: formatBlank(rules[domain]._name ? '当前' : '', rule[recog.handler].title),
|
||||
url: rule[recog.handler].docs,
|
||||
isDocs: true,
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
},
|
||||
() => {
|
||||
resolve();
|
||||
}
|
||||
);
|
||||
})
|
||||
)
|
||||
);
|
||||
return result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function getWebsiteRSSHub(data) {
|
||||
const { url } = data;
|
||||
const rules = parseRules(data.rules);
|
||||
let parsedDomain;
|
||||
try {
|
||||
parsedDomain = psl.parse(new URL(url).hostname);
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
if (parsedDomain && parsedDomain.domain) {
|
||||
const domain = parsedDomain.domain;
|
||||
if (rules[domain]) {
|
||||
const domainRules = [];
|
||||
for (const subdomainRules in rules[domain]) {
|
||||
if (subdomainRules[0] !== '_') {
|
||||
domainRules.push(...rules[domain][subdomainRules]);
|
||||
}
|
||||
}
|
||||
return domainRules.map((rule) => ({
|
||||
title: formatBlank(rules[domain]._name, rule.title),
|
||||
url: rule.docs,
|
||||
isDocs: true,
|
||||
}));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function getList(data) {
|
||||
const rules = parseRules(data.rules);
|
||||
for (const rule in rules) {
|
||||
for (const subrule in rules[rule]) {
|
||||
if (subrule[0] !== '_') {
|
||||
rules[rule][subrule].forEach((item) => {
|
||||
delete item.source;
|
||||
delete item.target;
|
||||
delete item.script;
|
||||
delete item.verification;
|
||||
delete item.test;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { useState } from "react"
|
||||
|
||||
import "./style.css"
|
||||
|
||||
function IndexNewtab() {
|
||||
const [data, setData] = useState("")
|
||||
|
||||
return (
|
||||
<div
|
||||
className="new-tab"
|
||||
style={{
|
||||
padding: 16,
|
||||
display: "flex",
|
||||
flexDirection: "column"
|
||||
}}>
|
||||
<h1>
|
||||
Welcome to your <a href="https://www.plasmo.com">Plasmo</a> Extension!
|
||||
</h1>
|
||||
<input onChange={(e) => setData(e.target.value)} value={data} />
|
||||
<footer>Crafted by @PlamoHQ</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default IndexNewtab
|
||||
@@ -0,0 +1,22 @@
|
||||
import { useState } from "react"
|
||||
|
||||
function IndexOptions() {
|
||||
const [data, setData] = useState("")
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
padding: 16
|
||||
}}>
|
||||
<h1>
|
||||
Welcome to your <a href="https://www.plasmo.com">Plasmo</a> Extension!
|
||||
</h1>
|
||||
<input onChange={(e) => setData(e.target.value)} value={data} />
|
||||
<footer>Crafted by @PlamoHQ</footer>{" "}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default IndexOptions
|
||||
@@ -0,0 +1,33 @@
|
||||
import { useState } from "react"
|
||||
import "./style.css"
|
||||
|
||||
function IndexPopup() {
|
||||
const [data, setData] = useState("")
|
||||
|
||||
return (
|
||||
<div className="min-w-[350px]">
|
||||
<div className="icons">
|
||||
<a className="icons-item icons-about" href="/options.html#/about"></a>
|
||||
<a className="icons-item icons-setting" href="/options.html#/setting"></a>
|
||||
</div>
|
||||
<div className="no-rss">
|
||||
<h2>( ´・・)ノ(._.`) <span data-i18n>rss not found</span></h2>
|
||||
<p data-i18n>join rsshub</p>
|
||||
</div>
|
||||
<div className="page-rss">
|
||||
<h2 data-i18n>current page rss</h2>
|
||||
<ul></ul>
|
||||
</div>
|
||||
<div className="page-rsshub">
|
||||
<h2 data-i18n>current page RSSHub</h2>
|
||||
<ul></ul>
|
||||
</div>
|
||||
<div className="website-rsshub">
|
||||
<h2 data-i18n>current site RSSHub</h2>
|
||||
<ul></ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default IndexPopup
|
||||
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1564303021552" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3669" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512.23 960.22c-247.43 0-448-200.57-448-448s200.58-448 448-448 448 200.58 448 448-200.57 448-448 448z m-56-503.83v279.67a56 56 0 1 0 112 0V456.39a56 56 0 1 0-112 0z m0-168.17a56 56 0 1 0 56-56 55.88 55.88 0 0 0-56 56z m0 0" fill="" p-id="3670"></path></svg>
|
||||
|
Before Width: | Height: | Size: 634 B |
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1564226990819" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1117" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M962.496 448.96c-3.584-19.84-22.656-39.808-42.304-44.288l-14.72-3.392c-34.624-10.432-65.536-33.536-84.992-67.328-19.648-33.984-24.128-72.576-15.616-107.968 0 0 0 0 0 0l4.288-13.824c5.952-19.264-1.792-45.76-17.216-58.816 0 0-13.824-11.712-52.992-34.304-39.168-22.592-56.128-28.736-56.128-28.736-19.008-6.848-45.76-0.32-59.52 14.464L612.928 115.84C586.56 140.672 551.104 155.904 512 155.904c-39.232 0-74.88-15.36-101.248-40.384L400.832 104.832C387.136 90.048 360.32 83.52 341.312 90.368c0 0-17.024 6.144-56.256 28.736C245.952 141.696 232.128 153.344 232.128 153.344 216.768 166.4 209.024 192.832 214.976 212.16l4.288 14.016c8.448 35.328 3.904 73.856-15.68 107.776C184 367.872 152.896 391.04 118.08 401.408L103.808 404.672c-19.648 4.48-38.72 24.448-42.304 44.288 0 0-3.2 17.792-3.2 63.04 0 45.248 3.2 62.976 3.2 62.976 3.584 19.84 22.656 39.808 42.304 44.288l13.952 3.2c0 0 0 0 0 0 34.944 10.304 66.112 33.536 85.824 67.584 19.648 33.984 24.128 72.576 15.616 107.968 0 0 0 0 0 0l-4.224 13.76c-5.952 19.264 1.792 45.76 17.216 58.816 0 0 13.824 11.712 52.992 34.304 39.168 22.592 56.128 28.736 56.128 28.736 19.008 6.848 45.76 0.32 59.52-14.464l9.792-10.56c26.432-25.024 62.08-40.448 101.376-40.448 39.296 0 75.008 15.424 101.44 40.512 0 0 0 0 0.064 0l9.728 10.496c13.76 14.784 40.512 21.312 59.52 14.464 0 0 17.024-6.144 56.256-28.736 39.168-22.592 52.928-34.304 52.928-34.304 15.424-13.056 23.168-39.488 17.216-58.816l-4.352-14.208c-8.32-35.264-3.84-73.664 15.744-107.52 19.648-34.048 50.88-57.216 85.824-67.584 0 0 0-0.064 0-0.064l13.952-3.2c19.648-4.48 38.72-24.448 42.304-44.288 0 0 3.2-17.792 3.2-63.04C965.696 466.752 962.496 448.96 962.496 448.96zM512 692.928c-99.904 0-180.928-81.024-180.928-180.928S412.096 331.136 512 331.136s180.928 81.024 180.928 180.928S611.904 692.928 512 692.928z" p-id="1118"></path></svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"access key": "Access key",
|
||||
"about": "About",
|
||||
"click to set": "Click to set",
|
||||
"configuration required if access keys enabled": "Configuration is only required if the instance has access keys enabled, keep it off if you don't know the situation",
|
||||
"copied": "Copied",
|
||||
"copy": "Copy",
|
||||
"current page rss": "RSS on the current site",
|
||||
"current page RSSHub": "RSSHub for the current page",
|
||||
"custom rsshub domain": "Custom RSSHub domain name",
|
||||
"current site RSSHub": "RSSHub for the current site",
|
||||
"documentation": "Info",
|
||||
"enable": "Enable",
|
||||
"i will update automatically and you can": "I will update automatically, and you can",
|
||||
"updating": "Updating",
|
||||
"update now": "Update Now",
|
||||
"before update": "before update",
|
||||
"after automatic update": "after automatic update",
|
||||
"full remote updates are disabled due to browser limitations": "Full remote updates are disabled due to browser limitations",
|
||||
"enter rsshub domain": "Please enter your RSSHub domain name, leave it blank to use the official domain name",
|
||||
"for more rules join us": "For more rules support, <a target=\"_blank\" href=\"https://docs.rsshub.app/en/joinus/quick-start.html\">join us</a>!",
|
||||
"general": "General",
|
||||
"generate access code": "Generate access code",
|
||||
"hot key": "Hot key",
|
||||
"join rsshub": "Participate in the <a href=\"https://docs.rsshub.app/en/\"> to make everything RSS-able!",
|
||||
"list of rules": "List of rules",
|
||||
"local reader": "Local reader",
|
||||
"one-click subscription": "One-click subscription",
|
||||
"notifications and reminders": "Notifications and reminders",
|
||||
"required access key": "Required, please enter the correct access key",
|
||||
"required address": "Required. Please enter you %{service} address",
|
||||
"required extension base URI": "Required. Please enter the %{service} extension URL after installation",
|
||||
"requires reader support": "Requires reader support, such as Reeder, etc.",
|
||||
"rss not found": "No RSS found",
|
||||
"rsshub radar options": "RSSHub Radar Options",
|
||||
"rules": "Rules",
|
||||
"rules update": "Rules update",
|
||||
"settings": "Settings",
|
||||
"show corner badge": "Show corner badge",
|
||||
"subscribe to": "Subscribe to",
|
||||
"subscribe to local reader": "Subscribe to local reader",
|
||||
"successfully saved": "Successfully saved",
|
||||
"updated time ago": "%{hours}h %{minutes}m since last update",
|
||||
"version": "Version",
|
||||
|
||||
"rsshub radar info": "RSSHub Radar is a spin-off of <a target=\"_blank\" href=\"https://docs.rsshub.app/en/\">RSSHub</a> that helps you quickly discover and subscribe to RSS and RSSHub for your current site, and the project is <a target=\"_blank\" href=\"https://github.com/DIYgod/RSSHub-Radar\">open source</a> under the MIT license and is completely free to use, but as the project grows in size, it also needs to be funded to sustain its maintenance and development",
|
||||
"sponsored development": "Sponsored development of RSSHub Radar: <a target=\"_blank\" href=\"https://docs.rsshub.app/en/support/\">https://docs.rsshub.app/en/support/</a>",
|
||||
"update log": "Update log",
|
||||
"question feedback": "Question Feedback",
|
||||
"rsshub documentation": "RSSHub Documentation: <a target=\"_blank\" href=\"https://docs.rsshub.app/en/\">https://docs.rsshub.app/en/</a>",
|
||||
"everything is possible with rss": "Everything is possible with RSS"
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"about": "Acerca de",
|
||||
"access key": "Clave de acceso",
|
||||
"click to set": "Hacer click para establecer",
|
||||
"configuration required if access keys enabled": "La configuración solo es necesaria si las claves de acceso están habilitada. Mantenlo desactivado en caso de duda",
|
||||
"copied": "Copiado",
|
||||
"copy": "Copiar",
|
||||
"current page rss": "RSS en esta página",
|
||||
"current page RSSHub": "RSSHub para página actual",
|
||||
"custom rsshub domain": "Dominio RSSHub personalizado",
|
||||
"current site RSSHub": "RSSHub para website actual",
|
||||
"documentation": "Info",
|
||||
"enable": "Activar",
|
||||
"full remote updates are disabled due to browser limitations": "Las actualizaciones remotas están desactivadas debido a las limitaciones del navegador",
|
||||
"enter rsshub domain": "Introduce to dominio de RSSHub, deja el espacio en blanco para utilizar el dominio oficial",
|
||||
"for more rules join us": "Para más reglas <a target=\"_blank\" href=\"https://docs.rsshub.app/en/joinus/quick-start.html\">únete</a>!",
|
||||
"general": "General",
|
||||
"generate access code": "Generar código de acceso",
|
||||
"hot key": "Hot key",
|
||||
"join rsshub": "Únete a <a href=\"https://docs.rsshub.app/en/\">RSSHub</a> para hacer todo accesible mediante RSS!",
|
||||
"list of rules": "Lista de reglas",
|
||||
"local reader": "Lector local",
|
||||
"notifications and reminders": "Notificaciones y avisos",
|
||||
"one-click subscription": "Subscripción mediante un click",
|
||||
"required access key": "Obligatorio, por favor introduct la clave de acceso correcta",
|
||||
"required address": "Obligatorio. Por favor introduce tu dirección %{service}",
|
||||
"required extension base URI": "Obligatorio. Ingrese la URL de la extensión %{service} después de la instalación",
|
||||
"requires reader support": "Necesita tener un visor como Reeder o algo del estilo instalado ",
|
||||
"rss not found": "No se han encontrado RSS's",
|
||||
"rsshub radar options": "RSSHub Radar Configuración",
|
||||
"rules": "Reglas",
|
||||
"rules update": "Actualización de reglas",
|
||||
"settings": "Opciones",
|
||||
"show corner badge": "Mostrar insignia",
|
||||
"subscribe to": "Subscribirse a",
|
||||
"subscribe to local reader": "Subscribirse en lector local",
|
||||
"successfully saved": "Guardado",
|
||||
"updated time ago": "%{hours}h %{minutes}m desde la última actualización",
|
||||
"version": "Versión",
|
||||
|
||||
"rsshub radar info": "RSSHub Radar es un proyecto derivado de <a target=\"_blank\" href=\"https://docs.rsshub.app/en/\">RSSHub</a> que permite subscribrirse rápidamente al RSS y/o RSSHub del website actual. Es un proyecto <a target=\"_blank\" href=\"https://github.com/DIYgod/RSSHub-Radar\">open source</a> bajo licencia MIT y su uso es completamete libre y gratuito, pero a medida que el proyecto crece también necesita ser patrocinado para mantener su soporte y desarrollo",
|
||||
"sponsored development": "Soporta el desarrollo de RSSHub Radar: <a target=\"_blank\" href=\"https://docs.rsshub.app/en/support/\">https://docs.rsshub.app/en/support/</a>",
|
||||
"update log": "Registro de cambios",
|
||||
"question feedback": "Feedback e incidencias",
|
||||
"rsshub documentation": "Documentación de RSSHub: <a target=\"_blank\" href=\"https://docs.rsshub.app/en/\">https://docs.rsshub.app/en/</a>",
|
||||
"everything is possible with rss": "Todo es posible con RSS"
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"about": "Honi buruz",
|
||||
"access key": "Sarrera-gakoa",
|
||||
"click to set": "Ezartzeko klik egin",
|
||||
"configuration required if access keys enabled": "Konfigurazioa sarrera-gakoak gaituta daudenean da derrigorrezkoa, ez gaitu ez baduzu egoera ezagutzen",
|
||||
"copied": "Kopiatuta",
|
||||
"copy": "Kopiatu",
|
||||
"current page rss": "Orrialde honetako RSSak",
|
||||
"current page RSSHub": "Orrialde honetarako RSSHub-ak",
|
||||
"custom rsshub domain": "RSSHub domeinu pertsonalizatua",
|
||||
"current site RSSHub": "Gune honetarako RSSHub-ak",
|
||||
"documentation": "Info",
|
||||
"enable": "Gaitu",
|
||||
"full remote updates are disabled due to browser limitations": "Urruneko eguneraketak desgaituta daude arakatzailearen mugak direla eta",
|
||||
"enter rsshub domain": "Mesedez sartu zure RSSHub domeinua, domeinu ofiziala erabiltzeko utzi zuriz",
|
||||
"for more rules join us": "Arau gehiago jasatzeko <a target=\"_blank\" href=\"https://docs.rsshub.app/en/joinus/quick-start.html\">batu zaitez</a>!",
|
||||
"general": "Orokorra",
|
||||
"generate access code": "Sarrera kodea sortu",
|
||||
"hot key": "Hot key",
|
||||
"join rsshub": "Gehitu zure burua <a href=\"https://docs.rsshub.app/en/\">RSSHub</a>-era dena RSS bitartez jaso ahal izateko!",
|
||||
"list of rules": "Arau-zerrenda",
|
||||
"local reader": "Bertako irakurgailua",
|
||||
"one-click subscription": "Klik bakarreko harpidetza",
|
||||
"notifications and reminders": "Jakinarazpenak",
|
||||
"required access key": "Nahitaezkoa, mesedez sartu sarrera-gako zuzena",
|
||||
"required address": "Nahitaezkoa. Mesedez sartu zure %{service} helbidea",
|
||||
"required extension base URI": "Nahitaezkoa. Sartu %{service} luzapenaren URLa instalatu ondoren",
|
||||
"requires reader support": "Reeder edo horrelakoren baten moduko irakurgailua behar du",
|
||||
"rss not found": "Ez da RSSrik aurkitu",
|
||||
"rsshub radar options": "RSSHub Radar Aukerak",
|
||||
"rules": "Arauak",
|
||||
"rules update": "Arauen eguneraketa",
|
||||
"settings": "Aukerak",
|
||||
"show corner badge": "Izkinako marka erakutsi",
|
||||
"subscribe to": "Harpidetu: ",
|
||||
"subscribe to local reader": "Harpidetu irakurgailu lokalean",
|
||||
"successfully saved": "Gordeta",
|
||||
"updated time ago": "%{hours}o %{minutes}m azken eguneraketatik",
|
||||
"version": "Bertsioa",
|
||||
|
||||
"rsshub radar info": "RSSHub Radar momentuko webgunearen RSS eta RSSHub-era modu azkar eta erraz batean harpidetzera laguntzen duen <a target=\"_blank\" href=\"https://docs.rsshub.app/en/\">RSSHub</a>-en proiektu eratorria da. Guztiz erabilera librea du eta MIT lizentziapean dagoen <a target=\"_blank\" href=\"https://github.com/DIYgod/RSSHub-Radar\">kode irekiko</a> proiektua da, baina handitzen doan heinean bere mantentze eta garapenari eusteko finantzazio beharra dauka.",
|
||||
"sponsored development": "RSSHub Radar laguntzeko: <a target=\"_blank\" href=\"https://docs.rsshub.app/en/support/\">https://docs.rsshub.app/en/support/</a>",
|
||||
"update log": "Eguneraketa-egunkaria",
|
||||
"question feedback": "Galdera eta atazak",
|
||||
"rsshub documentation": "RSSHub dokumentazioa: <a target=\"_blank\" href=\"https://docs.rsshub.app/en/\">https://docs.rsshub.app/en/</a>",
|
||||
"everything is possible with rss": "Dena da posible RSS-ekin"
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"access key": "Chave de acesso",
|
||||
"about": "Sobre",
|
||||
"click to set": "Clique para definir",
|
||||
"configuration required if access keys enabled": "Configuração só é requirida se a instância tiver chaves de acesso habilitadas, mantenha desligado se desconhecer a situação",
|
||||
"copied": "Copiado",
|
||||
"copy": "Copiar",
|
||||
"current page rss": "RSS no site atual",
|
||||
"current page RSSHub": "RSSHub para a página atual",
|
||||
"custom rsshub domain": "Nome de domínio personalizado RSSHub",
|
||||
"current site RSSHub": "RSSHub para o site atual",
|
||||
"documentation": "Informação",
|
||||
"enable": "Habilitar",
|
||||
"full remote updates are disabled due to browser limitations": "As actualizações remotas são desactivadas devido a limitações do navegador",
|
||||
"enter rsshub domain": "Por favor insira o seu nome de domínio RSSHub, deixe em branco para usar o nome de domínio oficial",
|
||||
"for more rules join us": "Para suporte a mais regras, <a target=\"_blank\" href=\"https://docs.rsshub.app/en/joinus/quick-start.html\">junte-se a nós</a>!",
|
||||
"general": "Geral",
|
||||
"generate access code": "Gerar código de acesso",
|
||||
"hot key": "Tecla de atalho",
|
||||
"join rsshub": "Participe no <a href=\"https://docs.rsshub.app/en/\"> para tornar tudo em RSS!",
|
||||
"list of rules": "Lista de regras",
|
||||
"local reader": "Leitor local",
|
||||
"one-click subscription": "Sobrescrever com um-clique",
|
||||
"notifications and reminders": "Notificações e lembretes",
|
||||
"required access key": "Obrigatório, por favor insira a chave de acesso correta",
|
||||
"required address": "Obrigatório. Por favor insira o seu endereço de %{service}",
|
||||
"required extension base URI": "Obrigatório. Insira o URL da extensão %{service} após a instalação",
|
||||
"requires reader support": "Requer suporte a leitor, tais como Reeder, etc.",
|
||||
"rss not found": "Nenhuma RSS encontrada",
|
||||
"rsshub radar options": "Opções RSSHub Radar",
|
||||
"rules": "Regras",
|
||||
"rules update": "Atualização das regras",
|
||||
"settings": "Definições",
|
||||
"show corner badge": "Mostrar canto do distintivo",
|
||||
"subscribe to": "Subscrever para",
|
||||
"subscribe to local reader": "Subscrever para leitor local",
|
||||
"successfully saved": "Gurdaddo com sucesso",
|
||||
"updated time ago": "%{hours}h %{minutes}m desde a última atualização",
|
||||
"version": "Versão",
|
||||
|
||||
"rsshub radar info": "RSSHub Radar é um subproduto do <a target=\"_blank\" href=\"https://docs.rsshub.app/en/\">RSSHub</a> que o ajuda rapidamente a descobrir e subscrever RSS e RSSHub para o seu site atual, e o projeto é de <a target=\"_blank\" href=\"https://github.com/DIYgod/RSSHub-Radar\">código aberto</a> sob licença do MIT e é completamente gratuito para ser usado, mas á medida que o projeto cresce em tamanho, também precisa de ser financiado para sustentar a sua manutenção e desenvolvimento",
|
||||
"sponsored development": "Desenvolvimento patrocinado do RSSHub Radar: <a target=\"_blank\" href=\"https://docs.rsshub.app/en/support/\">https://docs.rsshub.app/en/support/</a>",
|
||||
"update log": "Histórico de atualização",
|
||||
"question feedback": "Questões e Feedback",
|
||||
"rsshub documentation": "Documentação RSSHub: <a target=\"_blank\" href=\"https://docs.rsshub.app/en/\">https://docs.rsshub.app/en/</a>",
|
||||
"everything is possible with rss": "Tudo é possível com RSS"
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"about": "关于",
|
||||
"access key": "访问密钥",
|
||||
"click to set": "点此设置",
|
||||
"configuration required if access keys enabled": "只有实例启用了访问密钥,才需要配置,如果你不清楚情况,请保持关闭",
|
||||
"copied": "已复制",
|
||||
"copy": "复制",
|
||||
"current page rss": "当前页面上的 RSS",
|
||||
"current page RSSHub": "适用于当前页面的 RSSHub",
|
||||
"custom rsshub domain": "自定义 RSSHub 域名",
|
||||
"current site RSSHub": "适用于当前网站的 RSSHub",
|
||||
"documentation": "文档",
|
||||
"enable": "开启",
|
||||
"i will update automatically and you can": "我会自动更新,你也可以",
|
||||
"updating": "更新中",
|
||||
"update now": "立即更新",
|
||||
"before update": "前更新",
|
||||
"after automatic update": "后自动更新",
|
||||
"full remote updates are disabled due to browser limitations": "由于浏览器限制,完整的远程更新被禁用",
|
||||
"enter rsshub domain": "请输入你的 RSSHub 域名,留空使用官方域名",
|
||||
"for more rules join us": "更多规则支持中,快来<a target=\"_blank\" href=\"https://docs.rsshub.app/joinus/quick-start.html\">参与我们</a>吧!",
|
||||
"general": "常规",
|
||||
"generate access code": "生成访问码",
|
||||
"hot key": "快捷键",
|
||||
"join rsshub": "参与到 <a href=\"https://docs.rsshub.app\">RSSHub</a> 让万物皆可 RSS 吧!",
|
||||
"list of rules": "规则列表",
|
||||
"local reader": "本地阅读器",
|
||||
"notifications and reminders": "通知与提醒",
|
||||
"one-click subscription": "一键订阅",
|
||||
"required address": "必填,请输入你的 %{service} 地址",
|
||||
"required extension base URI": "必填,请输入你安装完成后的%{service}插件地址",
|
||||
"required access key": "必填,请输入正确的访问密钥",
|
||||
"requires reader support": "需要阅读器支持,如 Reeder 等",
|
||||
"rss not found": "当前页面没有检测到 RSS",
|
||||
"rsshub radar options": "RSSHub Radar 选项",
|
||||
"rules": "规则列表",
|
||||
"rules update": "规则更新",
|
||||
"settings": "设置",
|
||||
"show corner badge": "角标提醒",
|
||||
"subscribe to": "订阅到",
|
||||
"subscribe to local reader": "订阅到本地阅读器",
|
||||
"successfully saved": "保存成功",
|
||||
"updated time ago": "%{hours}小时 %{minutes}分钟 前更新",
|
||||
"version": "版本",
|
||||
|
||||
"rsshub radar info": "RSSHub Radar 是 <a target=\"_blank\" href=\"https://docs.rsshub.app\">RSSHub</a> 的衍生项目,她可以帮助你快速发现和订阅当前网站的 RSS 和 RSSHub,项目<a target=\"_blank\" href=\"https://github.com/DIYgod/RSSHub-Radar\">采用 MIT 许可开源</a>,使用完全免费,但是随着项目规模的增长,也需要有相应的资金支持才能持续项目的维护与开发",
|
||||
"sponsored development": "赞助 RSSHub Radar 的开发: <a target=\"_blank\" href=\"https://docs.rsshub.app/support/\">https://docs.rsshub.app/support/</a>",
|
||||
"update log": "更新日志",
|
||||
"question feedback": "问题反馈",
|
||||
"rsshub documentation": "RSSHub 文档: <a target=\"_blank\" href=\"https://docs.rsshub.app\">https://docs.rsshub.app</a>",
|
||||
"everything is possible with rss": "万物皆可 RSS"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
mode: "jit",
|
||||
darkMode: "class",
|
||||
content: ["./**/*.tsx"],
|
||||
plugins: []
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "plasmo/templates/tsconfig.base",
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
".plasmo/index.d.ts",
|
||||
"./**/*.ts",
|
||||
"./**/*.tsx"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"~*": [
|
||||
"./src/*"
|
||||
]
|
||||
},
|
||||
"baseUrl": "."
|
||||
}
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const VueLoaderPlugin = require('vue-loader/lib/plugin');
|
||||
|
||||
module.exports = {
|
||||
|
||||
mode: 'production',
|
||||
|
||||
devtool: false,
|
||||
|
||||
performance: {
|
||||
maxEntrypointSize: 1000000,
|
||||
},
|
||||
|
||||
entry: {
|
||||
'popup': './src/js/popup/index.js',
|
||||
'content': './src/js/content/index.js',
|
||||
'background': './src/js/background/index.js',
|
||||
'options': './src/js/options/index.js',
|
||||
'sandbox': './src/js/sandbox/index.js',
|
||||
},
|
||||
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: '[name].js',
|
||||
publicPath: '/',
|
||||
},
|
||||
|
||||
resolve: {
|
||||
modules: ['node_modules'],
|
||||
extensions: ['.js', '.less'],
|
||||
fallback: {
|
||||
'stream': require.resolve('stream-browserify'),
|
||||
'buffer': require.resolve('buffer/'),
|
||||
'http': require.resolve('stream-http'),
|
||||
"url": require.resolve("url/"),
|
||||
"https": require.resolve("https-browserify"),
|
||||
"timers": require.resolve("timers-browserify"),
|
||||
"process": require.resolve("process/browser"),
|
||||
}
|
||||
},
|
||||
|
||||
module: {
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
enforce: 'pre',
|
||||
loader: 'eslint-loader',
|
||||
include: path.resolve(__dirname, '../src/js'),
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: [
|
||||
'template-string-optimize-loader',
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
presets: ['@babel/preset-env'],
|
||||
plugins: [
|
||||
[
|
||||
"component",
|
||||
{
|
||||
"libraryName": "element-ui",
|
||||
"styleLibraryName": "theme-chalk"
|
||||
}
|
||||
],
|
||||
],
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'vue-style-loader',
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
postcssOptions: {
|
||||
plugins: [
|
||||
require('autoprefixer'),
|
||||
require('cssnano')({
|
||||
preset: 'default',
|
||||
}),
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [
|
||||
'vue-style-loader',
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
postcssOptions: {
|
||||
plugins: [
|
||||
require('autoprefixer'),
|
||||
require('cssnano')({
|
||||
preset: 'default',
|
||||
}),
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
'less-loader'
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
'vue-style-loader',
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
postcssOptions: {
|
||||
plugins: [
|
||||
require('autoprefixer'),
|
||||
require('cssnano')({
|
||||
preset: 'default',
|
||||
}),
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
'sass-loader'
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader'
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg)$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
'limit': 40000
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
loader: 'svg-inline-loader'
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].css'
|
||||
}),
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: 'src/assets',
|
||||
to: '',
|
||||
},
|
||||
],
|
||||
}),
|
||||
new VueLoaderPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
VERSION: JSON.stringify(require('./src/assets/manifest.json').version)
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
Buffer: ['buffer', 'Buffer'],
|
||||
process: 'process/browser',
|
||||
}),
|
||||
],
|
||||
};
|
||||