mirror of
https://github.com/tachiyomiorg/website.git
synced 2024-12-21 07:31:58 +01:00
Rewrite extensions components to setup syntax (#21)
* Rewrite extensions components to setup syntax. * Format md.use. * Import ElementPlus components directly for three-shaking. * Fix SSR setting. * Fix missing loading indicator in extensions page.
This commit is contained in:
parent
359833502a
commit
1d1bf5fba9
@ -57,6 +57,7 @@
|
|||||||
"stylelint": "^15.10.3",
|
"stylelint": "^15.10.3",
|
||||||
"stylelint-stylus": "^0.18.0",
|
"stylelint-stylus": "^0.18.0",
|
||||||
"stylus": "^0.60.0",
|
"stylus": "^0.60.0",
|
||||||
|
"unplugin-element-plus": "^0.8.0",
|
||||||
"vite-plugin-eslint": "^1.8.1",
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
"vitepress": "1.0.0-rc.10",
|
"vitepress": "1.0.0-rc.10",
|
||||||
"vitepress-plugin-tabs": "^0.3.0",
|
"vitepress-plugin-tabs": "^0.3.0",
|
||||||
|
101
website/pnpm-lock.yaml
generated
101
website/pnpm-lock.yaml
generated
@ -1,9 +1,5 @@
|
|||||||
lockfileVersion: '6.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
settings:
|
|
||||||
autoInstallPeers: true
|
|
||||||
excludeLinksFromLockfile: false
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@iconify-prerendered/vue-mdi':
|
'@iconify-prerendered/vue-mdi':
|
||||||
specifier: ^0.23.1689058119
|
specifier: ^0.23.1689058119
|
||||||
@ -109,6 +105,9 @@ devDependencies:
|
|||||||
stylus:
|
stylus:
|
||||||
specifier: ^0.60.0
|
specifier: ^0.60.0
|
||||||
version: 0.60.0
|
version: 0.60.0
|
||||||
|
unplugin-element-plus:
|
||||||
|
specifier: ^0.8.0
|
||||||
|
version: 0.8.0
|
||||||
vite-plugin-eslint:
|
vite-plugin-eslint:
|
||||||
specifier: ^1.8.1
|
specifier: ^1.8.1
|
||||||
version: 1.8.1(eslint@8.48.0)(vite@4.4.9)
|
version: 1.8.1(eslint@8.48.0)(vite@4.4.9)
|
||||||
@ -1013,6 +1012,20 @@ packages:
|
|||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@rollup/pluginutils@5.0.4:
|
||||||
|
resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
rollup: ^1.20.0||^2.0.0||^3.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
rollup:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@types/estree': 1.0.1
|
||||||
|
estree-walker: 2.0.2
|
||||||
|
picomatch: 2.3.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@shuding/opentype.js@1.4.0-beta.0:
|
/@shuding/opentype.js@1.4.0-beta.0:
|
||||||
resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==}
|
resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==}
|
||||||
engines: {node: '>= 8.0.0'}
|
engines: {node: '>= 8.0.0'}
|
||||||
@ -1540,6 +1553,14 @@ packages:
|
|||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/anymatch@3.1.3:
|
||||||
|
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
dependencies:
|
||||||
|
normalize-path: 3.0.0
|
||||||
|
picomatch: 2.3.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/argparse@1.0.10:
|
/argparse@1.0.10:
|
||||||
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
|
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1673,6 +1694,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
|
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/binary-extensions@2.2.0:
|
||||||
|
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/body-parser@1.20.1:
|
/body-parser@1.20.1:
|
||||||
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
|
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
|
||||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||||
@ -1781,6 +1807,21 @@ packages:
|
|||||||
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
|
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/chokidar@3.5.3:
|
||||||
|
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||||
|
engines: {node: '>= 8.10.0'}
|
||||||
|
dependencies:
|
||||||
|
anymatch: 3.1.3
|
||||||
|
braces: 3.0.2
|
||||||
|
glob-parent: 5.1.2
|
||||||
|
is-binary-path: 2.1.0
|
||||||
|
is-glob: 4.0.3
|
||||||
|
normalize-path: 3.0.0
|
||||||
|
readdirp: 3.6.0
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents: 2.3.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
/cli-cursor@4.0.0:
|
/cli-cursor@4.0.0:
|
||||||
resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
|
resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
|
||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
@ -2189,6 +2230,10 @@ packages:
|
|||||||
which-typed-array: 1.1.11
|
which-typed-array: 1.1.11
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/es-module-lexer@1.3.0:
|
||||||
|
resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/es-set-tostringtag@2.0.1:
|
/es-set-tostringtag@2.0.1:
|
||||||
resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==}
|
resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@ -3032,6 +3077,13 @@ packages:
|
|||||||
has-bigints: 1.0.2
|
has-bigints: 1.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/is-binary-path@2.1.0:
|
||||||
|
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dependencies:
|
||||||
|
binary-extensions: 2.2.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/is-boolean-object@1.1.2:
|
/is-boolean-object@1.1.2:
|
||||||
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
|
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@ -3986,6 +4038,13 @@ packages:
|
|||||||
type-fest: 1.4.0
|
type-fest: 1.4.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/readdirp@3.6.0:
|
||||||
|
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||||
|
engines: {node: '>=8.10.0'}
|
||||||
|
dependencies:
|
||||||
|
picomatch: 2.3.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/redent@4.0.0:
|
/redent@4.0.0:
|
||||||
resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==}
|
resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@ -4711,6 +4770,27 @@ packages:
|
|||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/unplugin-element-plus@0.8.0:
|
||||||
|
resolution: {integrity: sha512-jByUGY3FG2B8RJKFryqxx4eNtSTj+Hjlo8edcOdJymewndDQjThZ1pRUQHRjQsbKhTV2jEctJV7t7RJ405UL4g==}
|
||||||
|
engines: {node: '>=14.19.0'}
|
||||||
|
dependencies:
|
||||||
|
'@rollup/pluginutils': 5.0.4
|
||||||
|
es-module-lexer: 1.3.0
|
||||||
|
magic-string: 0.30.3
|
||||||
|
unplugin: 1.4.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- rollup
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/unplugin@1.4.0:
|
||||||
|
resolution: {integrity: sha512-5x4eIEL6WgbzqGtF9UV8VEC/ehKptPXDS6L2b0mv4FRMkJxRtjaJfOWDd6a8+kYbqsjklix7yWP0N3SUepjXcg==}
|
||||||
|
dependencies:
|
||||||
|
acorn: 8.10.0
|
||||||
|
chokidar: 3.5.3
|
||||||
|
webpack-sources: 3.2.3
|
||||||
|
webpack-virtual-modules: 0.5.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/upath@2.0.1:
|
/upath@2.0.1:
|
||||||
resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==}
|
resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@ -4909,6 +4989,15 @@ packages:
|
|||||||
'@vue/server-renderer': 3.3.4(vue@3.3.4)
|
'@vue/server-renderer': 3.3.4(vue@3.3.4)
|
||||||
'@vue/shared': 3.3.4
|
'@vue/shared': 3.3.4
|
||||||
|
|
||||||
|
/webpack-sources@3.2.3:
|
||||||
|
resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
|
||||||
|
engines: {node: '>=10.13.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/webpack-virtual-modules@0.5.0:
|
||||||
|
resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/which-boxed-primitive@1.0.2:
|
/which-boxed-primitive@1.0.2:
|
||||||
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -5022,3 +5111,7 @@ packages:
|
|||||||
/yoga-wasm-web@0.3.3:
|
/yoga-wasm-web@0.3.3:
|
||||||
resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==}
|
resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { defineConfig, loadEnv } from "vitepress";
|
import { defineConfig, loadEnv } from "vitepress";
|
||||||
|
import ElementPlus from "unplugin-element-plus/vite";
|
||||||
|
|
||||||
import markdownConfig from "./config/markdownConfig"; // For use with loading Markdown plugins
|
import markdownConfig from "./config/markdownConfig"; // For use with loading Markdown plugins
|
||||||
import themeConfig from "./config/themeConfig"; // Theme related config
|
import themeConfig from "./config/themeConfig"; // Theme related config
|
||||||
@ -30,4 +31,10 @@ export default defineConfig({
|
|||||||
generateFeed(context, hostname);
|
generateFeed(context, hostname);
|
||||||
generateOgImages(context);
|
generateOgImages(context);
|
||||||
},
|
},
|
||||||
|
vite: {
|
||||||
|
plugins: [ElementPlus({})],
|
||||||
|
ssr: {
|
||||||
|
noExternal: ["element-plus"],
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
@ -12,17 +12,17 @@ import shortcodes from "./shortcodes";
|
|||||||
|
|
||||||
const markdownConfig: MarkdownOptions = {
|
const markdownConfig: MarkdownOptions = {
|
||||||
config: (md) => {
|
config: (md) => {
|
||||||
md.use(attrs),
|
md
|
||||||
md.use(figure),
|
.use(attrs)
|
||||||
md.use(imgLazyload),
|
.use(figure)
|
||||||
md.use(imgMark),
|
.use(imgLazyload)
|
||||||
md.use(imgSize),
|
.use(imgMark)
|
||||||
md.use(include, {
|
.use(imgSize)
|
||||||
|
.use(include, {
|
||||||
currentPath: (env) => env.filePath,
|
currentPath: (env) => env.filePath,
|
||||||
}),
|
})
|
||||||
md.use(tabsMarkdownPlugin);
|
.use(tabsMarkdownPlugin)
|
||||||
|
.use(shortcode_plugin, shortcodes);
|
||||||
md.use(shortcode_plugin, shortcodes);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,57 +1,80 @@
|
|||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { toRefs } from "vue";
|
||||||
import { langName, simpleLangName } from "../../../config/scripts/languages";
|
import { langName, simpleLangName } from "../../../config/scripts/languages";
|
||||||
|
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
|
||||||
|
|
||||||
export default {
|
import {
|
||||||
props: ["extensions"],
|
ElForm,
|
||||||
emits: ["filters"],
|
ElFormItem,
|
||||||
data() {
|
ElInput,
|
||||||
return {
|
ElSelect,
|
||||||
filters: {
|
ElOption,
|
||||||
search: "",
|
ElRadioGroup,
|
||||||
lang: [],
|
ElRadio,
|
||||||
nsfw: "Show all",
|
} from "element-plus";
|
||||||
sort: "Ascending",
|
|
||||||
},
|
export type Nsfw = "Show all" | "NSFW" | "SFW";
|
||||||
};
|
export type Sort = "Ascending" | "Descending";
|
||||||
},
|
|
||||||
watch: {
|
const props = defineProps<{
|
||||||
filters: {
|
extensions: Extension[][];
|
||||||
handler(value) {
|
search: string;
|
||||||
this.$emit("filters", this.filters);
|
lang: string[];
|
||||||
},
|
nsfw: Nsfw;
|
||||||
deep: true,
|
sort: Sort;
|
||||||
},
|
}>();
|
||||||
},
|
|
||||||
methods: {
|
const { extensions } = toRefs(props);
|
||||||
simpleLangName,
|
|
||||||
langName,
|
defineEmits<{
|
||||||
},
|
(e: 'update:search', search: string): void;
|
||||||
};
|
(e: 'update:lang', lang: string[]): void,
|
||||||
|
(e: 'update:nsfw', nsfw: Nsfw): void,
|
||||||
|
(e: 'update:sort', sort: Sort): void,
|
||||||
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="filters-list">
|
<div class="filters-list">
|
||||||
<el-form :model="filters" label-width="120px">
|
<el-form label-width="120px">
|
||||||
<el-form-item label="Search:">
|
<el-form-item label="Search:">
|
||||||
<el-input v-model="filters.search" placeholder="Search extensions by name or ID..." clearable />
|
<el-input
|
||||||
|
:model-value="search"
|
||||||
|
placeholder="Search extensions by name or ID..."
|
||||||
|
clearable
|
||||||
|
@update:model-value="$emit('update:search', $event)"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Languages:">
|
<el-form-item label="Languages:">
|
||||||
<el-select v-model="filters.lang" placeholder="Show specific languages..." multiple clearable>
|
<el-select
|
||||||
<el-option
|
:model-value="lang"
|
||||||
v-for="[group] in extensions"
|
placeholder="Show specific languages..."
|
||||||
:key="group.lang"
|
multiple
|
||||||
:label="group.lang === 'en' ? simpleLangName(group.lang) : langName(group.lang)"
|
clearable
|
||||||
:value="group.lang"
|
@update:model-value="$emit('update:lang', $event)"
|
||||||
/>
|
>
|
||||||
</el-select>
|
<el-option
|
||||||
|
v-for="[group] in extensions"
|
||||||
|
:key="group.lang"
|
||||||
|
:label="group.lang === 'en' ? simpleLangName(group.lang) : langName(group.lang)"
|
||||||
|
:value="group.lang"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Sort by:">
|
<el-form-item label="Sort by:">
|
||||||
<el-radio-group v-model="filters.sort">
|
<el-radio-group
|
||||||
|
:model-value="sort"
|
||||||
|
@update:model-value="$emit('update:sort', $event)"
|
||||||
|
>
|
||||||
<el-radio label="Ascending"></el-radio>
|
<el-radio label="Ascending"></el-radio>
|
||||||
<el-radio label="Descending"></el-radio>
|
<el-radio label="Descending"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Display mode:">
|
<el-form-item label="Display mode:">
|
||||||
<el-radio-group v-model="filters.nsfw">
|
<el-radio-group
|
||||||
|
:model-value="nsfw"
|
||||||
|
@update:model-value="$emit('update:nsfw', $event)"
|
||||||
|
>
|
||||||
<el-radio label="NSFW"></el-radio>
|
<el-radio label="NSFW"></el-radio>
|
||||||
<el-radio label="SFW"></el-radio>
|
<el-radio label="SFW"></el-radio>
|
||||||
<el-radio label="Show all"></el-radio>
|
<el-radio label="Show all"></el-radio>
|
||||||
@ -67,4 +90,8 @@ export default {
|
|||||||
flex-direction: column
|
flex-direction: column
|
||||||
row-gap: 1rem
|
row-gap: 1rem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-select {
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,27 +1,25 @@
|
|||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { computed, toRefs } from "vue";
|
||||||
import { langName, simpleLangName } from "../../../config/scripts/languages";
|
import { langName, simpleLangName } from "../../../config/scripts/languages";
|
||||||
import ExtensionItem from "./ExtensionItem.vue";
|
import ExtensionItem from "./ExtensionItem.vue";
|
||||||
|
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
|
||||||
|
|
||||||
export default {
|
const props = defineProps<{ list: Extension[]; totalCount: number }>();
|
||||||
components: { ExtensionItem },
|
const { list } = toRefs(props);
|
||||||
props: ["list", "totalCount"],
|
|
||||||
computed: {
|
const groupName = computed(() => {
|
||||||
groupName: function () {
|
const firstItem = list.value[0];
|
||||||
const firstItem = this.list[0];
|
|
||||||
return firstItem.lang === "en" ? simpleLangName(firstItem.lang) : langName(firstItem.lang);
|
return firstItem.lang === "en"
|
||||||
},
|
? simpleLangName(firstItem.lang)
|
||||||
},
|
: langName(firstItem.lang);
|
||||||
methods: {
|
});
|
||||||
simpleLangName,
|
|
||||||
langName,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="extension-group">
|
<div class="extension-group">
|
||||||
<h2>
|
<h2>
|
||||||
{{ groupName }}
|
<span>{{ groupName }}</span>
|
||||||
|
|
||||||
<span class="extensions-total">
|
<span class="extensions-total">
|
||||||
Total:
|
Total:
|
||||||
@ -30,6 +28,7 @@ export default {
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<ExtensionItem
|
<ExtensionItem
|
||||||
v-for="extension in list"
|
v-for="extension in list"
|
||||||
:id="extension.pkg.replace('eu.kanade.tachiyomi.extension.', '')"
|
:id="extension.pkg.replace('eu.kanade.tachiyomi.extension.', '')"
|
||||||
@ -40,10 +39,12 @@ export default {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.extensions-total {
|
.extension-group h2 {
|
||||||
float: right
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: space-between
|
||||||
|
|
||||||
&-sum {
|
.extensions-total-sum {
|
||||||
color: var(--vp-c-brand)
|
color: var(--vp-c-brand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,24 @@
|
|||||||
<script>
|
<script setup lang="ts">
|
||||||
export default {
|
import { computed, toRefs } from "vue";
|
||||||
props: ["item"],
|
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
|
||||||
computed: {
|
|
||||||
pkgId: function () {
|
const props = defineProps<{ item: Extension }>();
|
||||||
return this.item.pkg.replace("eu.kanade.tachiyomi.extension.", "");
|
const { item } = toRefs(props);
|
||||||
},
|
|
||||||
pkgName: function () {
|
const pkgId = computed(() => {
|
||||||
return this.item.name.split(": ")[1];
|
return item.value.pkg.replace("eu.kanade.tachiyomi.extension.", "");
|
||||||
},
|
});
|
||||||
pkgVersion: function () {
|
|
||||||
return this.item.version;
|
const pkgName = computed(() => item.value.name.split(": ")[1]);
|
||||||
},
|
const pkgIsNsfw = computed(() => item.value.nsfw === 1);
|
||||||
pkgIsNsfw: function () {
|
|
||||||
return !!parseInt(this.item.nsfw);
|
const iconUrl = computed(() => {
|
||||||
},
|
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/icon/${item.value.pkg}.png`;
|
||||||
pkgHasReadme: function () {
|
});
|
||||||
return !!parseInt(this.item.hasReadme);
|
|
||||||
},
|
const apkUrl = computed(() => {
|
||||||
pkgHasChangelog: function () {
|
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/apk/${item.value.apk}`;
|
||||||
return !!parseInt(this.item.hasChangelog);
|
});
|
||||||
},
|
|
||||||
iconUrl: function () {
|
|
||||||
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/icon/${this.item.pkg}.png`;
|
|
||||||
},
|
|
||||||
apkUrl: function () {
|
|
||||||
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/apk/${this.item.apk}`;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -42,8 +33,8 @@ export default {
|
|||||||
{{ pkgId }}
|
{{ pkgId }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Badge v-if="pkgIsNsfw" type="danger" :text="pkgVersion" title="This extension contains NSFW entries." />
|
<Badge v-if="pkgIsNsfw" type="danger" :text="item.version" title="This extension contains NSFW entries." />
|
||||||
<Badge v-else type="info" :text="pkgVersion" title="This extension is free from NSFW entries." />
|
<Badge v-else type="info" :text="item.version" title="This extension is free from NSFW entries." />
|
||||||
<a :href="apkUrl" class="extension-download" title="Download APK" download>↓</a>
|
<a :href="apkUrl" class="extension-download" title="Download APK" download>↓</a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -53,14 +44,20 @@ export default {
|
|||||||
position: relative
|
position: relative
|
||||||
align-items: center
|
align-items: center
|
||||||
display: flex
|
display: flex
|
||||||
width: 100%
|
width: calc(100% + 1em)
|
||||||
padding: 0.5em 0
|
padding: 0.5em
|
||||||
margin: 0.8em 0
|
margin: 0.8em -0.5em
|
||||||
border-radius: 8px
|
border-radius: 8px
|
||||||
gap: 0.675rem
|
gap: 0.675rem
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--vp-c-bg-soft-mute)
|
background-color: var(--vp-c-bg-soft)
|
||||||
|
}
|
||||||
|
|
||||||
|
&:target {
|
||||||
|
background-color: var(--vp-c-brand-soft)
|
||||||
|
border-radius: 8px
|
||||||
|
transition: 500ms background-color
|
||||||
}
|
}
|
||||||
|
|
||||||
.anchor {
|
.anchor {
|
||||||
@ -142,6 +139,8 @@ export default {
|
|||||||
border: 1px solid var(--vp-c-divider)
|
border: 1px solid var(--vp-c-divider)
|
||||||
border-radius: 8px
|
border-radius: 8px
|
||||||
padding: 0.5em
|
padding: 0.5em
|
||||||
|
margin: 0.8em 0
|
||||||
|
width: 100%
|
||||||
|
|
||||||
.extension-icon {
|
.extension-icon {
|
||||||
margin-left: 0
|
margin-left: 0
|
||||||
@ -152,10 +151,4 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:target {
|
|
||||||
background-color: var(--vp-c-bg-soft-mute)
|
|
||||||
border-radius: 8px
|
|
||||||
transition: 500ms background-color
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,21 +1,28 @@
|
|||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { computed, toRefs } from "vue";
|
||||||
import ExtensionGroup from "./ExtensionGroup.vue";
|
import ExtensionGroup from "./ExtensionGroup.vue";
|
||||||
|
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
|
||||||
|
|
||||||
export default {
|
const props = defineProps<{ extensions: Extension[][] }>();
|
||||||
components: { ExtensionGroup },
|
const { extensions } = toRefs(props);
|
||||||
props: ["extensions"],
|
|
||||||
computed: {
|
const totalCount = computed(() => {
|
||||||
totalCount() {
|
return extensions.value.reduce((sum, item) => sum + item.length, 0);
|
||||||
return this.extensions.reduce((sum, item) => sum + item.length, 0);
|
});
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="extension-list">
|
<div class="extension-list">
|
||||||
<ExtensionGroup v-for="group in extensions" :key="group[0].lang" :list="group" :class="group[0].lang" :total-count="totalCount" />
|
<ExtensionGroup
|
||||||
|
v-for="group in extensions"
|
||||||
|
:key="group[0].lang"
|
||||||
|
:list="group"
|
||||||
|
:class="group[0].lang"
|
||||||
|
:total-count="totalCount"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.extension-list {
|
.extension-list {
|
||||||
> div {
|
> div {
|
||||||
|
@ -1,19 +1,29 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import groupBy from "lodash.groupby";
|
import groupBy from "lodash.groupby";
|
||||||
|
import { ElLoading } from "element-plus";
|
||||||
|
|
||||||
import { simpleLangName } from "../../../config/scripts/languages";
|
import { simpleLangName } from "../../../config/scripts/languages";
|
||||||
import ExtensionFilters from "./ExtensionFilters.vue";
|
import ExtensionFilters from "./ExtensionFilters.vue";
|
||||||
import ExtensionList from "./ExtensionList.vue";
|
import ExtensionList from "./ExtensionList.vue";
|
||||||
import useExtensionsRepositoryQuery from "../../queries/useExtensionsRepositoryQuery";
|
import useExtensionsRepositoryQuery from "../../queries/useExtensionsRepositoryQuery";
|
||||||
import { computed, onUpdated, ref } from 'vue';
|
import { computed, nextTick, onMounted, onUpdated, reactive, ref, watch } from 'vue';
|
||||||
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
|
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
|
||||||
|
import type { Nsfw, Sort } from "./ExtensionFilters.vue";
|
||||||
|
|
||||||
const { data: extensions, isLoading } = useExtensionsRepositoryQuery();
|
const { data: extensions, isLoading } = useExtensionsRepositoryQuery({
|
||||||
|
select: (response) => {
|
||||||
|
const values: Extension[][] = Object.values(groupBy(response, "lang"));
|
||||||
|
values.sort(languageComparator)
|
||||||
|
|
||||||
const filters = ref({
|
return values
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const filters = reactive({
|
||||||
search: "",
|
search: "",
|
||||||
lang: [] as string[],
|
lang: [] as string[],
|
||||||
nsfw: "Show all",
|
nsfw: "Show all" as Nsfw,
|
||||||
sort: "Ascending",
|
sort: "Ascending" as Sort,
|
||||||
});
|
});
|
||||||
|
|
||||||
function languageComparator(a: Extension[], b: Extension[]) {
|
function languageComparator(a: Extension[], b: Extension[]) {
|
||||||
@ -40,33 +50,26 @@ function languageComparator(a: Extension[], b: Extension[]) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupedExtensions = computed(() => {
|
|
||||||
const values: Extension[][] = Object.values(groupBy(extensions.value, "lang"));
|
|
||||||
values.sort(languageComparator)
|
|
||||||
|
|
||||||
return values
|
|
||||||
})
|
|
||||||
|
|
||||||
const filteredExtensions = computed(() => {
|
const filteredExtensions = computed(() => {
|
||||||
const filtered: Extension[][] = [];
|
const filtered: Extension[][] = [];
|
||||||
|
|
||||||
for (const group of groupedExtensions.value) {
|
for (const group of (extensions.value ?? [])) {
|
||||||
let filteredGroup = filters.value.lang.length
|
let filteredGroup = filters.lang.length
|
||||||
? (filters.value.lang.includes(group[0].lang) ? group : [])
|
? (filters.lang.includes(group[0].lang) ? group : [])
|
||||||
: group;
|
: group;
|
||||||
|
|
||||||
if (filters.value.search) {
|
if (filters.search) {
|
||||||
filteredGroup = filteredGroup.filter(
|
filteredGroup = filteredGroup.filter(
|
||||||
(ext) =>
|
(ext) =>
|
||||||
ext.name.toLowerCase().includes(filters.value.search.toLowerCase()) ||
|
ext.name.toLowerCase().includes(filters.search.toLowerCase()) ||
|
||||||
ext.sources.some((source) => source.id.includes(filters.value.search))
|
ext.sources.some((source) => source.id.includes(filters.search))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
filteredGroup = filteredGroup.filter((ext) =>
|
filteredGroup = filteredGroup.filter((ext) =>
|
||||||
filters.value.nsfw === "Show all" ? true : ext.nsfw === (filters.value.nsfw === "NSFW" ? 1 : 0)
|
filters.nsfw === "Show all" ? true : ext.nsfw === (filters.nsfw === "NSFW" ? 1 : 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (filters.value.sort && filters.value.sort === "Descending") {
|
if (filters.sort && filters.sort === "Descending") {
|
||||||
filteredGroup = filteredGroup.reverse();
|
filteredGroup = filteredGroup.reverse();
|
||||||
}
|
}
|
||||||
if (filteredGroup.length) {
|
if (filteredGroup.length) {
|
||||||
@ -77,15 +80,46 @@ const filteredExtensions = computed(() => {
|
|||||||
return filtered;
|
return filtered;
|
||||||
});
|
});
|
||||||
|
|
||||||
onUpdated(() => {
|
const loadingInstance = ref<ReturnType<typeof ElLoading['service']>>();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadingInstance.value = ElLoading.service({
|
||||||
|
target: ".extensions",
|
||||||
|
fullscreen: false,
|
||||||
|
background: "transparent",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(extensions, async () => {
|
||||||
if (window.location.hash) {
|
if (window.location.hash) {
|
||||||
window.location.replace(window.location.hash);
|
await nextTick()
|
||||||
|
document.getElementById(window.location.hash.substring(1))
|
||||||
|
?.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch([isLoading, loadingInstance], async ([newIsLoading]) => {
|
||||||
|
if (!newIsLoading) {
|
||||||
|
loadingInstance.value?.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ExtensionFilters :extensions="groupedExtensions" @filters="filters = $event" />
|
<ExtensionFilters
|
||||||
<div class="loading" v-if="isLoading" v-loading.lock="isLoading" style="min-height: 200px"></div>
|
:extensions="extensions ?? []"
|
||||||
<ExtensionList v-else :extensions="filteredExtensions" />
|
v-model:search="filters.search"
|
||||||
|
v-model:lang="filters.lang"
|
||||||
|
v-model:nsfw="filters.nsfw"
|
||||||
|
v-model:sort="filters.sort"
|
||||||
|
/>
|
||||||
|
<div class="extensions">
|
||||||
|
<ExtensionList v-if="!isLoading" :extensions="filteredExtensions" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.extensions {
|
||||||
|
min-height: 200px
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -5,8 +5,6 @@ import DefaultTheme from "vitepress/theme";
|
|||||||
import "./styles/base.styl";
|
import "./styles/base.styl";
|
||||||
|
|
||||||
// Import Global plugins
|
// Import Global plugins
|
||||||
import ElementPlus from "element-plus";
|
|
||||||
import "element-plus/dist/index.css";
|
|
||||||
import "element-plus/theme-chalk/dark/css-vars.css";
|
import "element-plus/theme-chalk/dark/css-vars.css";
|
||||||
|
|
||||||
import { VueQueryPlugin } from "@tanstack/vue-query";
|
import { VueQueryPlugin } from "@tanstack/vue-query";
|
||||||
@ -19,7 +17,6 @@ import { IconDownload, IconNewspaperVariant, IconBugReport } from "@iconify-prer
|
|||||||
export default {
|
export default {
|
||||||
extends: DefaultTheme,
|
extends: DefaultTheme,
|
||||||
enhanceApp({ app }) {
|
enhanceApp({ app }) {
|
||||||
app.use(ElementPlus);
|
|
||||||
app.use(VueQueryPlugin);
|
app.use(VueQueryPlugin);
|
||||||
enhanceAppWithTabs(app);
|
enhanceAppWithTabs(app);
|
||||||
app.component("IconDownload", IconDownload);
|
app.component("IconDownload", IconDownload);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useQuery } from "@tanstack/vue-query";
|
import { UseQueryOptions, useQuery } from "@tanstack/vue-query";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { GITHUB_EXTENSION_JSON } from "../../config/constants";
|
import { GITHUB_EXTENSION_JSON } from "../../config/constants";
|
||||||
|
|
||||||
@ -26,14 +26,11 @@ export interface Source {
|
|||||||
hasCloudflare: string;
|
hasCloudflare: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GitHubAsset {
|
type UseExtensionsRepositoryQueryOptions<S = Extension[]> =
|
||||||
name: string;
|
UseQueryOptions<Extension[], Error, S>
|
||||||
content_type: string;
|
|
||||||
browser_download_url: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function useExtensionsRepositoryQuery() {
|
export default function useExtensionsRepositoryQuery<S = Extension[]>(options: UseExtensionsRepositoryQueryOptions<S> = {}) {
|
||||||
return useQuery({
|
return useQuery<Extension[], Error, S>({
|
||||||
queryKey: ["extensions"],
|
queryKey: ["extensions"],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await axios.get<Extension[]>(GITHUB_EXTENSION_JSON);
|
const { data } = await axios.get<Extension[]>(GITHUB_EXTENSION_JSON);
|
||||||
@ -42,5 +39,6 @@ export default function useExtensionsRepositoryQuery() {
|
|||||||
},
|
},
|
||||||
initialData: () => [],
|
initialData: () => [],
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
|
...options,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -217,3 +217,10 @@ main :where(h1, h2, h3, h4, h5, h6) + figure {
|
|||||||
margin-right: 4px
|
margin-right: 4px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component: Element Plus
|
||||||
|
*/
|
||||||
|
body {
|
||||||
|
--el-color-primary: var(--vp-c-brand-1)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user