mirror of
https://github.com/tachiyomiorg/website.git
synced 2024-11-01 07:25:06 +01:00
Add a changelogs page and other minor fixes (#15)
* Add a changelogs page. * Fix local search highlight colors. * Make changelog headers a link. * Replace GitHub links with local ones. * Fix missing `Badge` component. * Show release contributors. * Add missing flex-wrap to mobile devices. * Add missing `alt` attribute to the avatar. * Use `@theme` alias while importing components from the theme. * Minor design tweaks to the extensions items. * Show contributors on WhatsNew component as well. * Fix extensions page not centered. * Show sidebar on the changelogs page. * Fix missing link replacements. * Add missing unmentioned credits.
This commit is contained in:
parent
489801174e
commit
31169bd527
@ -73,6 +73,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iconify-prerendered/vue-mdi": "^0.23.1689058119",
|
"@iconify-prerendered/vue-mdi": "^0.23.1689058119",
|
||||||
|
"@octokit/rest": "^20.0.1",
|
||||||
|
"@octokit/types": "^11.1.0",
|
||||||
"@tanstack/vue-query": "^4.34.0",
|
"@tanstack/vue-query": "^4.34.0",
|
||||||
"axios": "^1.5.0",
|
"axios": "^1.5.0",
|
||||||
"element-plus": "^2.3.12",
|
"element-plus": "^2.3.12",
|
||||||
|
@ -4,6 +4,12 @@ dependencies:
|
|||||||
'@iconify-prerendered/vue-mdi':
|
'@iconify-prerendered/vue-mdi':
|
||||||
specifier: ^0.23.1689058119
|
specifier: ^0.23.1689058119
|
||||||
version: 0.23.1689058119(vue@3.3.4)
|
version: 0.23.1689058119(vue@3.3.4)
|
||||||
|
'@octokit/rest':
|
||||||
|
specifier: ^20.0.1
|
||||||
|
version: 20.0.1
|
||||||
|
'@octokit/types':
|
||||||
|
specifier: ^11.1.0
|
||||||
|
version: 11.1.0
|
||||||
'@tanstack/vue-query':
|
'@tanstack/vue-query':
|
||||||
specifier: ^4.34.0
|
specifier: ^4.34.0
|
||||||
version: 4.34.0(vue@3.3.4)
|
version: 4.34.0(vue@3.3.4)
|
||||||
@ -757,6 +763,111 @@ packages:
|
|||||||
fastq: 1.15.0
|
fastq: 1.15.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@octokit/auth-token@4.0.0:
|
||||||
|
resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/core@5.0.0:
|
||||||
|
resolution: {integrity: sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
dependencies:
|
||||||
|
'@octokit/auth-token': 4.0.0
|
||||||
|
'@octokit/graphql': 7.0.1
|
||||||
|
'@octokit/request': 8.1.1
|
||||||
|
'@octokit/request-error': 5.0.0
|
||||||
|
'@octokit/types': 11.1.0
|
||||||
|
before-after-hook: 2.2.3
|
||||||
|
universal-user-agent: 6.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/endpoint@9.0.0:
|
||||||
|
resolution: {integrity: sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
dependencies:
|
||||||
|
'@octokit/types': 11.1.0
|
||||||
|
is-plain-object: 5.0.0
|
||||||
|
universal-user-agent: 6.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/graphql@7.0.1:
|
||||||
|
resolution: {integrity: sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
dependencies:
|
||||||
|
'@octokit/request': 8.1.1
|
||||||
|
'@octokit/types': 11.1.0
|
||||||
|
universal-user-agent: 6.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/openapi-types@18.0.0:
|
||||||
|
resolution: {integrity: sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/plugin-paginate-rest@8.0.0(@octokit/core@5.0.0):
|
||||||
|
resolution: {integrity: sha512-2xZ+baZWUg+qudVXnnvXz7qfrTmDeYPCzangBVq/1gXxii/OiS//4shJp9dnCCvj1x+JAm9ji1Egwm1BA47lPQ==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
peerDependencies:
|
||||||
|
'@octokit/core': '>=5'
|
||||||
|
dependencies:
|
||||||
|
'@octokit/core': 5.0.0
|
||||||
|
'@octokit/types': 11.1.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/plugin-request-log@4.0.0(@octokit/core@5.0.0):
|
||||||
|
resolution: {integrity: sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
peerDependencies:
|
||||||
|
'@octokit/core': '>=5'
|
||||||
|
dependencies:
|
||||||
|
'@octokit/core': 5.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/plugin-rest-endpoint-methods@9.0.0(@octokit/core@5.0.0):
|
||||||
|
resolution: {integrity: sha512-KquMF/VB1IkKNiVnzJKspY5mFgGyLd7HzdJfVEGTJFzqu9BRFNWt+nwTCMuUiWc72gLQhRWYubTwOkQj+w/1PA==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
peerDependencies:
|
||||||
|
'@octokit/core': '>=5'
|
||||||
|
dependencies:
|
||||||
|
'@octokit/core': 5.0.0
|
||||||
|
'@octokit/types': 11.1.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/request-error@5.0.0:
|
||||||
|
resolution: {integrity: sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
dependencies:
|
||||||
|
'@octokit/types': 11.1.0
|
||||||
|
deprecation: 2.3.1
|
||||||
|
once: 1.4.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/request@8.1.1:
|
||||||
|
resolution: {integrity: sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
dependencies:
|
||||||
|
'@octokit/endpoint': 9.0.0
|
||||||
|
'@octokit/request-error': 5.0.0
|
||||||
|
'@octokit/types': 11.1.0
|
||||||
|
is-plain-object: 5.0.0
|
||||||
|
universal-user-agent: 6.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/rest@20.0.1:
|
||||||
|
resolution: {integrity: sha512-wROV21RwHQIMNb2Dgd4+pY+dVy1Dwmp85pBrgr6YRRDYRBu9Gb+D73f4Bl2EukZSj5hInq2Tui9o7gAQpc2k2Q==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
dependencies:
|
||||||
|
'@octokit/core': 5.0.0
|
||||||
|
'@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.0)
|
||||||
|
'@octokit/plugin-request-log': 4.0.0(@octokit/core@5.0.0)
|
||||||
|
'@octokit/plugin-rest-endpoint-methods': 9.0.0(@octokit/core@5.0.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@octokit/types@11.1.0:
|
||||||
|
resolution: {integrity: sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==}
|
||||||
|
dependencies:
|
||||||
|
'@octokit/openapi-types': 18.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@pkgjs/parseargs@0.11.0:
|
/@pkgjs/parseargs@0.11.0:
|
||||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@ -1554,6 +1665,10 @@ packages:
|
|||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/before-after-hook@2.2.3:
|
||||||
|
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/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}
|
||||||
@ -1899,6 +2014,10 @@ packages:
|
|||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/deprecation@2.3.1:
|
||||||
|
resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/destroy@1.2.0:
|
/destroy@1.2.0:
|
||||||
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
||||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||||
@ -2987,7 +3106,6 @@ packages:
|
|||||||
/is-plain-object@5.0.0:
|
/is-plain-object@5.0.0:
|
||||||
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
|
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-regex@1.1.4:
|
/is-regex@1.1.4:
|
||||||
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
|
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
|
||||||
@ -3589,7 +3707,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
wrappy: 1.0.2
|
wrappy: 1.0.2
|
||||||
dev: true
|
|
||||||
|
|
||||||
/onetime@5.1.2:
|
/onetime@5.1.2:
|
||||||
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
||||||
@ -4576,6 +4693,10 @@ packages:
|
|||||||
tiny-inflate: 1.0.3
|
tiny-inflate: 1.0.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/universal-user-agent@6.0.0:
|
||||||
|
resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/unpipe@1.0.0:
|
/unpipe@1.0.0:
|
||||||
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@ -4840,7 +4961,6 @@ packages:
|
|||||||
|
|
||||||
/wrappy@1.0.2:
|
/wrappy@1.0.2:
|
||||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/write-file-atomic@5.0.1:
|
/write-file-atomic@5.0.1:
|
||||||
resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
|
resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
const APP_VERSION = "0.14.6";
|
||||||
|
|
||||||
const nav = [
|
const nav = [
|
||||||
{
|
{
|
||||||
text: "Documentation",
|
text: "Documentation",
|
||||||
@ -5,7 +7,7 @@ const nav = [
|
|||||||
activeMatch: "/docs/",
|
activeMatch: "/docs/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "0.14.6",
|
text: APP_VERSION,
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
text: "Download",
|
text: "Download",
|
||||||
@ -13,7 +15,7 @@ const nav = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Changelog",
|
text: "Changelog",
|
||||||
link: "https://github.com/tachiyomiorg/tachiyomi/releases/latest",
|
link: `/changelogs/#v${APP_VERSION}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Contributing",
|
text: "Contributing",
|
||||||
|
@ -3,6 +3,7 @@ import { getSidebar } from "vitepress-plugin-auto-sidebar";
|
|||||||
const sidebar = {
|
const sidebar = {
|
||||||
"/docs/": defaultSidebar(),
|
"/docs/": defaultSidebar(),
|
||||||
"/forks/": defaultSidebar(),
|
"/forks/": defaultSidebar(),
|
||||||
|
"/changelogs/": defaultSidebar(),
|
||||||
"/news/": getSidebar({
|
"/news/": getSidebar({
|
||||||
contentRoot: "/src/",
|
contentRoot: "/src/",
|
||||||
contentDirs: ["news"],
|
contentDirs: ["news"],
|
||||||
@ -120,6 +121,10 @@ function defaultSidebar() {
|
|||||||
text: "Extensions",
|
text: "Extensions",
|
||||||
link: "/extensions/",
|
link: "/extensions/",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: "Changelogs",
|
||||||
|
link: "/changelogs/",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: "Forks",
|
text: "Forks",
|
||||||
link: "/forks/",
|
link: "/forks/",
|
||||||
|
@ -59,7 +59,7 @@ const themeConfig: DefaultTheme.Config = {
|
|||||||
lastUpdated: {
|
lastUpdated: {
|
||||||
text: "Last updated",
|
text: "Last updated",
|
||||||
formatOptions: {
|
formatOptions: {
|
||||||
dateStyle: "long",
|
dateStyle: "short",
|
||||||
timeStyle: "short",
|
timeStyle: "short",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
69
website/src/.vitepress/theme/components/Changelogs.vue
Normal file
69
website/src/.vitepress/theme/components/Changelogs.vue
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import MarkdownIt from "markdown-it";
|
||||||
|
import { data as changelogs } from "../data/changelogs.data";
|
||||||
|
import Contributors from "./Contributors.vue";
|
||||||
|
|
||||||
|
const md = new MarkdownIt();
|
||||||
|
|
||||||
|
function renderMarkdown(string: string | null | undefined) {
|
||||||
|
const body = string ?? "No changelog provided.";
|
||||||
|
const flavoredString = body
|
||||||
|
.split(/---\r\n\r\n### Checksums|---\r\n\r\nMD5/)[0]
|
||||||
|
.replace(/(?<=\(|(, ))@(.*?)(?=\)|(, ))/g, "[@$2](https://github.com/$2)")
|
||||||
|
.replace(/#(\d+)/g, '[#$1](https://github.com/tachiyomiorg/tachiyomi/issues/$1)')
|
||||||
|
.replace(/^Check out the .*past release notes.* if you're.*$/m, "")
|
||||||
|
.replace(/https\:\/\/github.com\/tachiyomiorg\/tachiyomi\/releases\/tag\/(.*?)/g, "#$1")
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
return md.render(flavoredString);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateFormatter = new Intl.DateTimeFormat("en", {
|
||||||
|
dateStyle: "medium",
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-for="(release, index) of changelogs"
|
||||||
|
:key="release.tag_name"
|
||||||
|
>
|
||||||
|
<h2 :id="release.tag_name">
|
||||||
|
<a
|
||||||
|
:href="release.html_url"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
{{ release.tag_name.substring(1) }}
|
||||||
|
</a>
|
||||||
|
<Badge v-if="index === 0" type="tip" text="Latest" />
|
||||||
|
<a
|
||||||
|
class="header-anchor"
|
||||||
|
:href="`#${release.tag_name}`"
|
||||||
|
:aria-label="`Permalink to "${release.tag_name}"`"
|
||||||
|
/>
|
||||||
|
</h2>
|
||||||
|
<time :datetime="release.published_at!">
|
||||||
|
{{ dateFormatter.format(new Date(release.published_at!)) }}
|
||||||
|
</time>
|
||||||
|
<div v-html="renderMarkdown(release.body)"></div>
|
||||||
|
<Contributors
|
||||||
|
:body="release.body!"
|
||||||
|
:author="release.author.login"
|
||||||
|
:tag="release.tag_name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
h2 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
time {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
}
|
||||||
|
</style>
|
109
website/src/.vitepress/theme/components/Contributors.vue
Normal file
109
website/src/.vitepress/theme/components/Contributors.vue
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, toRefs } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps<{ body: string; author: string; tag: string; }>();
|
||||||
|
const { body, author, tag } = toRefs(props);
|
||||||
|
|
||||||
|
function isHigherThan(tagName: string, reference: string) {
|
||||||
|
return reference.localeCompare(tagName, undefined, { numeric: true, sensitivity: "base" }) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const notMentioned = computed(() => {
|
||||||
|
return isHigherThan("v0.8.5", tag.value) ? ['arkon'] : [];
|
||||||
|
});
|
||||||
|
|
||||||
|
const nonExistent = ref<string[]>([])
|
||||||
|
|
||||||
|
const contributors = computed(() => {
|
||||||
|
const list = [...body.value.matchAll(/(?<=\(|(, ))@(.*?)(?=\)|(, ))/g)]
|
||||||
|
.map((match) => match[2])
|
||||||
|
const uncredited = author.value.includes('[bot]')
|
||||||
|
? notMentioned.value
|
||||||
|
: [author.value, ...notMentioned.value];
|
||||||
|
|
||||||
|
return [...new Set([...uncredited, ...list])].filter((user) => !nonExistent.value.includes(user));
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
const listFormatter = new Intl.ListFormat("en", {
|
||||||
|
style: "long",
|
||||||
|
type: "conjunction",
|
||||||
|
});
|
||||||
|
|
||||||
|
const contributorsText = computed(() => {
|
||||||
|
if (contributors.value.length <= 3) {
|
||||||
|
return listFormatter.format(contributors.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return listFormatter.format([
|
||||||
|
...contributors.value.slice(0, 2),
|
||||||
|
`${contributors.value.length - 2} other contributors`
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
function addToNonExistent(user: string) {
|
||||||
|
if (!nonExistent.value.includes(user)) {
|
||||||
|
nonExistent.value.push(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="contributors" v-if="contributors.length > 0">
|
||||||
|
<h3>Contributors</h3>
|
||||||
|
<ul>
|
||||||
|
<li
|
||||||
|
v-for="contributor of contributors"
|
||||||
|
:key="contributor"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
:href="`https://github.com/${contributor}`"
|
||||||
|
target="_blank"
|
||||||
|
:title="`${contributor} profile on GitHub`"
|
||||||
|
:aria-label="`${contributor} profile on GitHub`"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="`https://github.com/${contributor}.png?size=32`"
|
||||||
|
:alt="`@${contributor} profile picture`"
|
||||||
|
@error="addToNonExistent(contributor)"
|
||||||
|
loading="lazy"
|
||||||
|
class="avatar"
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="names">
|
||||||
|
{{ contributorsText }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.contributors {
|
||||||
|
ul {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
|
li + li {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: var(--vp-shadow-1);
|
||||||
|
border: 1px solid var(--vp-c-divider);
|
||||||
|
}
|
||||||
|
|
||||||
|
.names {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -30,14 +30,12 @@ export default {
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
<div
|
<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.', '')"
|
||||||
:key="extension.apk"
|
:key="extension.apk"
|
||||||
class="extension"
|
:item="extension"
|
||||||
>
|
/>
|
||||||
<ExtensionItem :item="extension" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -30,14 +30,12 @@ export default {
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
<div
|
<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.', '')"
|
||||||
:key="extension.apk"
|
:key="extension.apk"
|
||||||
class="extension"
|
:item="extension"
|
||||||
>
|
/>
|
||||||
<ExtensionItem :item="extension" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -30,7 +30,8 @@ export default {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template v-if="item">
|
<template>
|
||||||
|
<div class="extension">
|
||||||
<a :href="`#${pkgId}`" class="anchor" aria-hidden="true" @click.stop>#</a>
|
<a :href="`#${pkgId}`" class="anchor" aria-hidden="true" @click.stop>#</a>
|
||||||
<img class="extension-icon" :src="iconUrl" loading="lazy" width="42" height="42" />
|
<img class="extension-icon" :src="iconUrl" loading="lazy" width="42" height="42" />
|
||||||
<div class="extension-text">
|
<div class="extension-text">
|
||||||
@ -44,23 +45,28 @@ export default {
|
|||||||
<Badge v-if="pkgIsNsfw" type="danger" :text="pkgVersion" title="This extension contains NSFW entries." />
|
<Badge v-if="pkgIsNsfw" type="danger" :text="pkgVersion" 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="pkgVersion" 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>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.extension {
|
.extension {
|
||||||
|
position: relative
|
||||||
align-items: center
|
align-items: center
|
||||||
display: flex
|
display: flex
|
||||||
padding: 0.5em 1.5em
|
width: 100%
|
||||||
margin: 0.8em 0.2em
|
padding: 0.5em 0
|
||||||
|
margin: 0.8em 0
|
||||||
border-radius: 8px
|
border-radius: 8px
|
||||||
|
gap: 0.675rem
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--vp-c-bg-soft-mute)
|
background-color: var(--vp-c-bg-soft-mute)
|
||||||
}
|
}
|
||||||
|
|
||||||
.anchor {
|
.anchor {
|
||||||
margin-left: 0.2em
|
position: absolute
|
||||||
margin-right: 0.2em
|
left: 0
|
||||||
|
margin-left: -1em
|
||||||
font-size: 1.4em
|
font-size: 1.4em
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}
|
}
|
||||||
@ -70,25 +76,34 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.extension-icon {
|
.extension-icon {
|
||||||
margin: 0.2em 0.5em
|
flex-shrink: 0
|
||||||
|
margin-left: -4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-text {
|
.extension-text {
|
||||||
flex: 1
|
flex-grow: 1
|
||||||
|
min-width: 0
|
||||||
|
|
||||||
.upper {
|
.upper {
|
||||||
font-weight: 600
|
font-weight: 600
|
||||||
|
overflow: hidden
|
||||||
|
text-overflow: ellipsis
|
||||||
|
white-space: nowrap
|
||||||
|
|
||||||
.badge {
|
.badge {
|
||||||
font-weight: 400
|
font-weight: 400
|
||||||
margin-left: 8px
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.lower {
|
.lower {
|
||||||
|
margin-top: 0.25rem
|
||||||
color: #6c757d
|
color: #6c757d
|
||||||
font-family: monospace
|
font-family: var(--vp-font-family-mono)
|
||||||
font-size: 0.9rem
|
font-size: 0.9rem
|
||||||
|
overflow: hidden
|
||||||
|
text-overflow: ellipsis
|
||||||
|
white-space: nowrap
|
||||||
|
line-height: 16px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +112,8 @@ export default {
|
|||||||
font-weight: 700
|
font-weight: 700
|
||||||
font-size: 1.4em
|
font-size: 1.4em
|
||||||
border-radius: 4px
|
border-radius: 4px
|
||||||
|
flex-shrink: 0
|
||||||
|
margin-right: -0.4em
|
||||||
|
|
||||||
.material-icons {
|
.material-icons {
|
||||||
color: white
|
color: white
|
||||||
@ -124,6 +141,11 @@ export default {
|
|||||||
.extension {
|
.extension {
|
||||||
border: 1px solid var(--vp-c-divider)
|
border: 1px solid var(--vp-c-divider)
|
||||||
border-radius: 8px
|
border-radius: 8px
|
||||||
|
padding: 0.5em
|
||||||
|
|
||||||
|
.extension-download {
|
||||||
|
margin-right: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import { computed, toRefs } from "vue";
|
import { computed, toRefs } from "vue";
|
||||||
import MarkdownIt from "markdown-it";
|
import MarkdownIt from "markdown-it";
|
||||||
import { data as release, type AppRelease } from "../data/release.data";
|
import { data as release, type AppRelease } from "../data/release.data";
|
||||||
|
import Contributors from "./Contributors.vue";
|
||||||
|
|
||||||
const props = defineProps<{ type: keyof AppRelease }>();
|
const props = defineProps<{ type: keyof AppRelease }>();
|
||||||
const { type } = toRefs(props);
|
const { type } = toRefs(props);
|
||||||
@ -11,6 +12,7 @@ const md = new MarkdownIt();
|
|||||||
const whatsNew = computed(() => {
|
const whatsNew = computed(() => {
|
||||||
const flavoredString = (release[type.value].body ?? "")
|
const flavoredString = (release[type.value].body ?? "")
|
||||||
.replace(/(?<=\(|(, ))@(.*?)(?=\)|(, ))/g, "[@$2](https://github.com/$2)")
|
.replace(/(?<=\(|(, ))@(.*?)(?=\)|(, ))/g, "[@$2](https://github.com/$2)")
|
||||||
|
.replace('https://github.com/tachiyomiorg/tachiyomi/releases', '/changelogs/');
|
||||||
|
|
||||||
return md.render(flavoredString);
|
return md.render(flavoredString);
|
||||||
})
|
})
|
||||||
@ -22,8 +24,12 @@ const whatsNew = computed(() => {
|
|||||||
<IconNewReleases />
|
<IconNewReleases />
|
||||||
<h2>What's new</h2>
|
<h2>What's new</h2>
|
||||||
</header>
|
</header>
|
||||||
<div v-html="whatsNew">
|
<div v-html="whatsNew" />
|
||||||
</div>
|
<Contributors
|
||||||
|
:body="release[type].body!"
|
||||||
|
:author="release[type].author.login"
|
||||||
|
:tag="release[type].tag_name"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="fullChangelog">
|
<div class="fullChangelog">
|
||||||
<p>
|
<p>
|
||||||
|
22
website/src/.vitepress/theme/data/changelogs.data.ts
Normal file
22
website/src/.vitepress/theme/data/changelogs.data.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { defineLoader } from "vitepress"
|
||||||
|
import { Octokit } from "@octokit/rest";
|
||||||
|
import type { GetResponseDataTypeFromEndpointMethod } from "@octokit/types";
|
||||||
|
|
||||||
|
const octokit = new Octokit();
|
||||||
|
|
||||||
|
type GitHubReleaseList = GetResponseDataTypeFromEndpointMethod<typeof octokit.repos.listReleases>;
|
||||||
|
|
||||||
|
declare const data: GitHubReleaseList;
|
||||||
|
export { data };
|
||||||
|
|
||||||
|
export default defineLoader({
|
||||||
|
async load(): Promise<GitHubReleaseList> {
|
||||||
|
const releases = await octokit.paginate(octokit.repos.listReleases, {
|
||||||
|
owner: "tachiyomiorg",
|
||||||
|
repo: "tachiyomi",
|
||||||
|
per_page: 100,
|
||||||
|
});
|
||||||
|
|
||||||
|
return releases;
|
||||||
|
}
|
||||||
|
});
|
@ -1,33 +1,30 @@
|
|||||||
import { defineLoader } from "vitepress"
|
import { defineLoader } from "vitepress"
|
||||||
import axios from "axios";
|
import { Octokit } from "@octokit/rest";
|
||||||
import { GITHUB_PREVIEW_API, GITHUB_STABLE_API } from "../../config/constants";
|
import type { GetResponseDataTypeFromEndpointMethod } from "@octokit/types";
|
||||||
|
|
||||||
|
const octokit = new Octokit();
|
||||||
|
|
||||||
|
type GitHubRelease = GetResponseDataTypeFromEndpointMethod<typeof octokit.repos.getLatestRelease>;
|
||||||
|
|
||||||
export interface AppRelease {
|
export interface AppRelease {
|
||||||
stable: GitHubRelease;
|
stable: GitHubRelease;
|
||||||
preview: GitHubRelease;
|
preview: GitHubRelease;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GitHubRelease {
|
|
||||||
body: string;
|
|
||||||
tag_name: string;
|
|
||||||
name: string;
|
|
||||||
assets: GitHubAsset[];
|
|
||||||
published_at: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GitHubAsset {
|
|
||||||
name: string;
|
|
||||||
content_type: string;
|
|
||||||
browser_download_url: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare const data: AppRelease;
|
declare const data: AppRelease;
|
||||||
export { data };
|
export { data };
|
||||||
|
|
||||||
export default defineLoader({
|
export default defineLoader({
|
||||||
async load(): Promise<AppRelease> {
|
async load(): Promise<AppRelease> {
|
||||||
const { data: stable } = await axios.get<GitHubRelease>(GITHUB_STABLE_API);
|
const { data: stable } = await octokit.repos.getLatestRelease({
|
||||||
const { data: preview } = await axios.get<GitHubRelease>(GITHUB_PREVIEW_API);
|
owner: "tachiyomiorg",
|
||||||
|
repo: "tachiyomi",
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: preview } = await octokit.repos.getLatestRelease({
|
||||||
|
owner: "tachiyomiorg",
|
||||||
|
repo: "tachiyomi-preview",
|
||||||
|
});
|
||||||
|
|
||||||
return { stable, preview };
|
return { stable, preview };
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import { enhanceAppWithTabs } from "vitepress-plugin-tabs/client";
|
|||||||
import { IconDownload, IconNewReleases, IconBugReport } from "@iconify-prerendered/vue-mdi";
|
import { IconDownload, IconNewReleases, IconBugReport } from "@iconify-prerendered/vue-mdi";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...DefaultTheme,
|
extends: DefaultTheme,
|
||||||
enhanceApp({ app }) {
|
enhanceApp({ app }) {
|
||||||
app.use(ElementPlus);
|
app.use(ElementPlus);
|
||||||
app.use(VueQueryPlugin);
|
app.use(VueQueryPlugin);
|
||||||
|
@ -114,6 +114,18 @@ html:not(.dark) {
|
|||||||
border-radius: 8px
|
border-radius: 8px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component: LocalSearch
|
||||||
|
*/
|
||||||
|
.VPLocalSearchBox {
|
||||||
|
--vp-local-search-highlight-bg: var(--vp-c-brand-soft);
|
||||||
|
--vp-local-search-highlight-text: var(--vp-c-brand-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .VPLocalSearchBox {
|
||||||
|
--vp-local-search-highlight-text: var(--vp-c-brand-lightest);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component: Image Figure
|
* Component: Image Figure
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
padding: 16px
|
padding: 16px
|
||||||
color: var(--vp-c-text-1)
|
color: var(--vp-c-text-1)
|
||||||
// background-color: var(--vp-code-block-bg)
|
// background-color: var(--vp-code-block-bg)
|
||||||
font-family: 'Roboto Mono', monospace
|
font-family: var(--vp-font-family-mono)
|
||||||
font-size: 0.85rem
|
font-size: 0.85rem
|
||||||
line-height: 1.5
|
line-height: 1.5
|
||||||
|
|
||||||
|
18
website/src/changelogs/index.md
Normal file
18
website/src/changelogs/index.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
title: Changelogs
|
||||||
|
description: Changelogs of all Tachiyomi stable releases.
|
||||||
|
lastUpdated: false
|
||||||
|
editLink: false
|
||||||
|
prev: false
|
||||||
|
next: false
|
||||||
|
---
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import Changelogs from "@theme/components/Changelogs.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
# Changelogs
|
||||||
|
|
||||||
|
Changelogs of all Tachiyomi stable releases, obtained from the GitHub repository.
|
||||||
|
|
||||||
|
<Changelogs />
|
@ -9,9 +9,9 @@ next: false
|
|||||||
---
|
---
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import DownloadButtons from "../.vitepress/theme/components/DownloadButtons.vue"
|
import DownloadButtons from "@theme/components/DownloadButtons.vue";
|
||||||
import ReleaseDate from "../.vitepress/theme/components/ReleaseDate.vue";
|
import ReleaseDate from "@theme/components/ReleaseDate.vue";
|
||||||
import WhatsNew from "../.vitepress/theme/components/WhatsNew.vue"
|
import WhatsNew from "@theme/components/WhatsNew.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
# Download
|
# Download
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
---
|
---
|
||||||
title: Extensions
|
title: Extensions
|
||||||
description: Browse and install the full list of sources for Tachiyomi.
|
description: Browse and install the full list of sources for Tachiyomi.
|
||||||
|
aside: false
|
||||||
|
lastUpdated: false
|
||||||
|
editLink: false
|
||||||
|
prev: false
|
||||||
|
next: false
|
||||||
---
|
---
|
||||||
|
|
||||||
# Extensions
|
# Extensions
|
||||||
@ -10,5 +15,5 @@ Web-based extensions page that enables users to browse and install additional so
|
|||||||
<ExtensionsWrapper/>
|
<ExtensionsWrapper/>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import ExtensionsWrapper from '../.vitepress/theme/components/Extensions/ExtensionsWrapper.vue'
|
import ExtensionsWrapper from '@theme/components/Extensions/ExtensionsWrapper.vue'
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
Reference in New Issue
Block a user