mirror of
https://github.com/tachiyomiorg/website.git
synced 2024-12-21 07:31:58 +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": {
|
||||
"@iconify-prerendered/vue-mdi": "^0.23.1689058119",
|
||||
"@octokit/rest": "^20.0.1",
|
||||
"@octokit/types": "^11.1.0",
|
||||
"@tanstack/vue-query": "^4.34.0",
|
||||
"axios": "^1.5.0",
|
||||
"element-plus": "^2.3.12",
|
||||
|
126
website/pnpm-lock.yaml
generated
126
website/pnpm-lock.yaml
generated
@ -4,6 +4,12 @@ dependencies:
|
||||
'@iconify-prerendered/vue-mdi':
|
||||
specifier: ^0.23.1689058119
|
||||
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':
|
||||
specifier: ^4.34.0
|
||||
version: 4.34.0(vue@3.3.4)
|
||||
@ -757,6 +763,111 @@ packages:
|
||||
fastq: 1.15.0
|
||||
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:
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
@ -1554,6 +1665,10 @@ packages:
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: true
|
||||
|
||||
/before-after-hook@2.2.3:
|
||||
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
|
||||
dev: false
|
||||
|
||||
/body-parser@1.20.1:
|
||||
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
@ -1899,6 +2014,10 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: true
|
||||
|
||||
/deprecation@2.3.1:
|
||||
resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==}
|
||||
dev: false
|
||||
|
||||
/destroy@1.2.0:
|
||||
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
@ -2987,7 +3106,6 @@ packages:
|
||||
/is-plain-object@5.0.0:
|
||||
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/is-regex@1.1.4:
|
||||
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
|
||||
@ -3589,7 +3707,6 @@ packages:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
dev: true
|
||||
|
||||
/onetime@5.1.2:
|
||||
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
||||
@ -4576,6 +4693,10 @@ packages:
|
||||
tiny-inflate: 1.0.3
|
||||
dev: true
|
||||
|
||||
/universal-user-agent@6.0.0:
|
||||
resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==}
|
||||
dev: false
|
||||
|
||||
/unpipe@1.0.0:
|
||||
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -4840,7 +4961,6 @@ packages:
|
||||
|
||||
/wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
dev: true
|
||||
|
||||
/write-file-atomic@5.0.1:
|
||||
resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
|
||||
|
@ -1,3 +1,5 @@
|
||||
const APP_VERSION = "0.14.6";
|
||||
|
||||
const nav = [
|
||||
{
|
||||
text: "Documentation",
|
||||
@ -5,7 +7,7 @@ const nav = [
|
||||
activeMatch: "/docs/",
|
||||
},
|
||||
{
|
||||
text: "0.14.6",
|
||||
text: APP_VERSION,
|
||||
items: [
|
||||
{
|
||||
text: "Download",
|
||||
@ -13,7 +15,7 @@ const nav = [
|
||||
},
|
||||
{
|
||||
text: "Changelog",
|
||||
link: "https://github.com/tachiyomiorg/tachiyomi/releases/latest",
|
||||
link: `/changelogs/#v${APP_VERSION}`,
|
||||
},
|
||||
{
|
||||
text: "Contributing",
|
||||
|
@ -3,6 +3,7 @@ import { getSidebar } from "vitepress-plugin-auto-sidebar";
|
||||
const sidebar = {
|
||||
"/docs/": defaultSidebar(),
|
||||
"/forks/": defaultSidebar(),
|
||||
"/changelogs/": defaultSidebar(),
|
||||
"/news/": getSidebar({
|
||||
contentRoot: "/src/",
|
||||
contentDirs: ["news"],
|
||||
@ -120,6 +121,10 @@ function defaultSidebar() {
|
||||
text: "Extensions",
|
||||
link: "/extensions/",
|
||||
},
|
||||
{
|
||||
text: "Changelogs",
|
||||
link: "/changelogs/",
|
||||
},
|
||||
{
|
||||
text: "Forks",
|
||||
link: "/forks/",
|
||||
|
@ -59,7 +59,7 @@ const themeConfig: DefaultTheme.Config = {
|
||||
lastUpdated: {
|
||||
text: "Last updated",
|
||||
formatOptions: {
|
||||
dateStyle: "long",
|
||||
dateStyle: "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>
|
||||
</h2>
|
||||
<div
|
||||
<ExtensionItem
|
||||
v-for="extension in list"
|
||||
:id="extension.pkg.replace('eu.kanade.tachiyomi.extension.', '')"
|
||||
:key="extension.apk"
|
||||
class="extension"
|
||||
>
|
||||
<ExtensionItem :item="extension" />
|
||||
</div>
|
||||
:item="extension"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -30,14 +30,12 @@ export default {
|
||||
</span>
|
||||
</span>
|
||||
</h2>
|
||||
<div
|
||||
<ExtensionItem
|
||||
v-for="extension in list"
|
||||
:id="extension.pkg.replace('eu.kanade.tachiyomi.extension.', '')"
|
||||
:key="extension.apk"
|
||||
class="extension"
|
||||
>
|
||||
<ExtensionItem :item="extension" />
|
||||
</div>
|
||||
:item="extension"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -30,37 +30,43 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<template v-if="item">
|
||||
<a :href="`#${pkgId}`" class="anchor" aria-hidden="true" @click.stop>#</a>
|
||||
<img class="extension-icon" :src="iconUrl" loading="lazy" width="42" height="42" />
|
||||
<div class="extension-text">
|
||||
<div class="upper">
|
||||
{{ pkgName }}
|
||||
</div>
|
||||
<div class="lower">
|
||||
{{ pkgId }}
|
||||
<template>
|
||||
<div class="extension">
|
||||
<a :href="`#${pkgId}`" class="anchor" aria-hidden="true" @click.stop>#</a>
|
||||
<img class="extension-icon" :src="iconUrl" loading="lazy" width="42" height="42" />
|
||||
<div class="extension-text">
|
||||
<div class="upper">
|
||||
{{ pkgName }}
|
||||
</div>
|
||||
<div class="lower">
|
||||
{{ pkgId }}
|
||||
</div>
|
||||
</div>
|
||||
<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." />
|
||||
<a :href="apkUrl" class="extension-download" title="Download APK" download>↓</a>
|
||||
</div>
|
||||
<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." />
|
||||
<a :href="apkUrl" class="extension-download" title="Download APK" download>↓</a>
|
||||
</template>
|
||||
|
||||
<style lang="stylus">
|
||||
.extension {
|
||||
position: relative
|
||||
align-items: center
|
||||
display: flex
|
||||
padding: 0.5em 1.5em
|
||||
margin: 0.8em 0.2em
|
||||
width: 100%
|
||||
padding: 0.5em 0
|
||||
margin: 0.8em 0
|
||||
border-radius: 8px
|
||||
gap: 0.675rem
|
||||
|
||||
&:hover {
|
||||
background-color: var(--vp-c-bg-soft-mute)
|
||||
}
|
||||
|
||||
.anchor {
|
||||
margin-left: 0.2em
|
||||
margin-right: 0.2em
|
||||
position: absolute
|
||||
left: 0
|
||||
margin-left: -1em
|
||||
font-size: 1.4em
|
||||
opacity: 0
|
||||
}
|
||||
@ -70,25 +76,34 @@ export default {
|
||||
}
|
||||
|
||||
.extension-icon {
|
||||
margin: 0.2em 0.5em
|
||||
flex-shrink: 0
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.extension-text {
|
||||
flex: 1
|
||||
flex-grow: 1
|
||||
min-width: 0
|
||||
|
||||
.upper {
|
||||
font-weight: 600
|
||||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
white-space: nowrap
|
||||
|
||||
.badge {
|
||||
font-weight: 400
|
||||
margin-left: 8px
|
||||
}
|
||||
}
|
||||
|
||||
.lower {
|
||||
margin-top: 0.25rem
|
||||
color: #6c757d
|
||||
font-family: monospace
|
||||
font-family: var(--vp-font-family-mono)
|
||||
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-size: 1.4em
|
||||
border-radius: 4px
|
||||
flex-shrink: 0
|
||||
margin-right: -0.4em
|
||||
|
||||
.material-icons {
|
||||
color: white
|
||||
@ -124,6 +141,11 @@ export default {
|
||||
.extension {
|
||||
border: 1px solid var(--vp-c-divider)
|
||||
border-radius: 8px
|
||||
padding: 0.5em
|
||||
|
||||
.extension-download {
|
||||
margin-right: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { computed, toRefs } from "vue";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import { data as release, type AppRelease } from "../data/release.data";
|
||||
import Contributors from "./Contributors.vue";
|
||||
|
||||
const props = defineProps<{ type: keyof AppRelease }>();
|
||||
const { type } = toRefs(props);
|
||||
@ -11,6 +12,7 @@ const md = new MarkdownIt();
|
||||
const whatsNew = computed(() => {
|
||||
const flavoredString = (release[type.value].body ?? "")
|
||||
.replace(/(?<=\(|(, ))@(.*?)(?=\)|(, ))/g, "[@$2](https://github.com/$2)")
|
||||
.replace('https://github.com/tachiyomiorg/tachiyomi/releases', '/changelogs/');
|
||||
|
||||
return md.render(flavoredString);
|
||||
})
|
||||
@ -22,8 +24,12 @@ const whatsNew = computed(() => {
|
||||
<IconNewReleases />
|
||||
<h2>What's new</h2>
|
||||
</header>
|
||||
<div v-html="whatsNew">
|
||||
</div>
|
||||
<div v-html="whatsNew" />
|
||||
<Contributors
|
||||
:body="release[type].body!"
|
||||
:author="release[type].author.login"
|
||||
:tag="release[type].tag_name"
|
||||
/>
|
||||
</div>
|
||||
<div class="fullChangelog">
|
||||
<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 axios from "axios";
|
||||
import { GITHUB_PREVIEW_API, GITHUB_STABLE_API } from "../../config/constants";
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import type { GetResponseDataTypeFromEndpointMethod } from "@octokit/types";
|
||||
|
||||
const octokit = new Octokit();
|
||||
|
||||
type GitHubRelease = GetResponseDataTypeFromEndpointMethod<typeof octokit.repos.getLatestRelease>;
|
||||
|
||||
export interface AppRelease {
|
||||
stable: 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;
|
||||
export { data };
|
||||
|
||||
export default defineLoader({
|
||||
async load(): Promise<AppRelease> {
|
||||
const { data: stable } = await axios.get<GitHubRelease>(GITHUB_STABLE_API);
|
||||
const { data: preview } = await axios.get<GitHubRelease>(GITHUB_PREVIEW_API);
|
||||
const { data: stable } = await octokit.repos.getLatestRelease({
|
||||
owner: "tachiyomiorg",
|
||||
repo: "tachiyomi",
|
||||
});
|
||||
|
||||
const { data: preview } = await octokit.repos.getLatestRelease({
|
||||
owner: "tachiyomiorg",
|
||||
repo: "tachiyomi-preview",
|
||||
});
|
||||
|
||||
return { stable, preview };
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import { enhanceAppWithTabs } from "vitepress-plugin-tabs/client";
|
||||
import { IconDownload, IconNewReleases, IconBugReport } from "@iconify-prerendered/vue-mdi";
|
||||
|
||||
export default {
|
||||
...DefaultTheme,
|
||||
extends: DefaultTheme,
|
||||
enhanceApp({ app }) {
|
||||
app.use(ElementPlus);
|
||||
app.use(VueQueryPlugin);
|
||||
|
@ -114,6 +114,18 @@ html:not(.dark) {
|
||||
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
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
@ -4,7 +4,7 @@
|
||||
padding: 16px
|
||||
color: var(--vp-c-text-1)
|
||||
// background-color: var(--vp-code-block-bg)
|
||||
font-family: 'Roboto Mono', monospace
|
||||
font-family: var(--vp-font-family-mono)
|
||||
font-size: 0.85rem
|
||||
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>
|
||||
import DownloadButtons from "../.vitepress/theme/components/DownloadButtons.vue"
|
||||
import ReleaseDate from "../.vitepress/theme/components/ReleaseDate.vue";
|
||||
import WhatsNew from "../.vitepress/theme/components/WhatsNew.vue"
|
||||
import DownloadButtons from "@theme/components/DownloadButtons.vue";
|
||||
import ReleaseDate from "@theme/components/ReleaseDate.vue";
|
||||
import WhatsNew from "@theme/components/WhatsNew.vue";
|
||||
</script>
|
||||
|
||||
# Download
|
||||
|
@ -1,6 +1,11 @@
|
||||
---
|
||||
title: Extensions
|
||||
description: Browse and install the full list of sources for Tachiyomi.
|
||||
aside: false
|
||||
lastUpdated: false
|
||||
editLink: false
|
||||
prev: false
|
||||
next: false
|
||||
---
|
||||
|
||||
# Extensions
|
||||
@ -10,5 +15,5 @@ Web-based extensions page that enables users to browse and install additional so
|
||||
<ExtensionsWrapper/>
|
||||
|
||||
<script setup>
|
||||
import ExtensionsWrapper from '../.vitepress/theme/components/Extensions/ExtensionsWrapper.vue'
|
||||
import ExtensionsWrapper from '@theme/components/Extensions/ExtensionsWrapper.vue'
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user