mirror of
https://github.com/tachiyomiorg/website.git
synced 2024-10-31 23:15:05 +01:00
Fix remaining eslint errors
This commit is contained in:
parent
e0da86ca0c
commit
bbac199151
@ -2,12 +2,8 @@ root = true
|
|||||||
|
|
||||||
[*]
|
[*]
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
indent_style = tab
|
indent_style = space
|
||||||
indent_size = 4
|
indent_size = 2
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
[*.yml]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
|
@ -9,7 +9,7 @@ module.exports = {
|
|||||||
'stylus/selector-type-no-unknown': null,
|
'stylus/selector-type-no-unknown': null,
|
||||||
'stylus/selector-list-comma': 'always',
|
'stylus/selector-list-comma': 'always',
|
||||||
'stylus/indentation': [
|
'stylus/indentation': [
|
||||||
'tab',
|
2,
|
||||||
{
|
{
|
||||||
indentInsideParens: 'twice',
|
indentInsideParens: 'twice',
|
||||||
},
|
},
|
||||||
|
@ -19,6 +19,9 @@ export default antfu({
|
|||||||
'docs/.vitepress/cache/**',
|
'docs/.vitepress/cache/**',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
typescript: true,
|
||||||
|
vue: true,
|
||||||
|
|
||||||
...compat.config({
|
...compat.config({
|
||||||
rules: {
|
rules: {
|
||||||
'comma-dangle': ['error', 'only-multiline'],
|
'comma-dangle': ['error', 'only-multiline'],
|
||||||
|
@ -1,72 +1,76 @@
|
|||||||
import process from "node:process"
|
import process from 'node:process'
|
||||||
import { URL, fileURLToPath } from "node:url"
|
import { URL, fileURLToPath } from 'node:url'
|
||||||
import { defineConfig, loadEnv } from "vitepress"
|
import { defineConfig, loadEnv } from 'vitepress'
|
||||||
import ElementPlus from "unplugin-element-plus/vite"
|
import ElementPlus from 'unplugin-element-plus/vite'
|
||||||
|
|
||||||
import markdownConfig from "./config/markdownConfig"
|
import markdownConfig from './config/markdownConfig'
|
||||||
|
|
||||||
// For use with loading Markdown plugins
|
// For use with loading Markdown plugins
|
||||||
import themeConfig from "./config/themeConfig"
|
import themeConfig from './config/themeConfig'
|
||||||
|
|
||||||
// Theme related config
|
// Theme related config
|
||||||
import headConfig from "./config/headConfig" // Provides how to generate Meta head tags
|
import headConfig from './config/headConfig'
|
||||||
|
|
||||||
import generateMeta from "./config/hooks/generateMeta"
|
// Provides how to generate Meta head tags
|
||||||
|
|
||||||
|
import generateMeta from './config/hooks/generateMeta'
|
||||||
|
|
||||||
// Enhanced meta generation
|
// Enhanced meta generation
|
||||||
import generateFeed from "./config/hooks/generateFeed" // Allows generation of RSS feed
|
import generateFeed from './config/hooks/generateFeed'
|
||||||
import generateOgImages from "./config/hooks/generateOgImages"
|
|
||||||
|
|
||||||
const title = "Tachiyomi"
|
// Allows generation of RSS feed
|
||||||
const description = "Discover and read manga, webtoons, comics, and more – easier than ever on your Android device."
|
import generateOgImages from './config/hooks/generateOgImages'
|
||||||
|
|
||||||
const env = loadEnv("", process.cwd())
|
const title = 'Tachiyomi'
|
||||||
const hostname: string = env.VITE_HOSTNAME || "http://localhost:4173"
|
const description = 'Discover and read manga, webtoons, comics, and more – easier than ever on your Android device.'
|
||||||
|
|
||||||
|
const env = loadEnv('', process.cwd())
|
||||||
|
const hostname: string = env.VITE_HOSTNAME || 'http://localhost:4173'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
outDir: "../dist",
|
outDir: '../dist',
|
||||||
lastUpdated: true,
|
lastUpdated: true,
|
||||||
cleanUrls: true,
|
cleanUrls: true,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
sitemap: {
|
sitemap: {
|
||||||
hostname,
|
hostname,
|
||||||
},
|
},
|
||||||
head: headConfig,
|
head: headConfig,
|
||||||
markdown: markdownConfig,
|
markdown: markdownConfig,
|
||||||
themeConfig,
|
themeConfig,
|
||||||
transformHead: async (context) => generateMeta(context, hostname),
|
transformHead: async context => generateMeta(context, hostname),
|
||||||
buildEnd: async (context) => {
|
buildEnd: async (context) => {
|
||||||
generateFeed(context, hostname)
|
generateFeed(context, hostname)
|
||||||
generateOgImages(context)
|
generateOgImages(context)
|
||||||
},
|
},
|
||||||
vite: {
|
vite: {
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: [
|
alias: [
|
||||||
{
|
{
|
||||||
// Used to show the release version on navbar.
|
// Used to show the release version on navbar.
|
||||||
find: /^.*\/VPNavBarMenu\.vue$/,
|
find: /^.*\/VPNavBarMenu\.vue$/,
|
||||||
replacement: fileURLToPath(
|
replacement: fileURLToPath(
|
||||||
new URL("./theme/components/CustomNavBarMenu.vue", import.meta.url),
|
new URL('./theme/components/CustomNavBarMenu.vue', import.meta.url),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
find: /^.*VPNavScreenMenu\.vue$/,
|
find: /^.*VPNavScreenMenu\.vue$/,
|
||||||
replacement: fileURLToPath(
|
replacement: fileURLToPath(
|
||||||
new URL("./theme/components/CustomNavScreenMenu.vue", import.meta.url),
|
new URL('./theme/components/CustomNavScreenMenu.vue', import.meta.url),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
find: /^.*VPSwitchAppearance\.vue$/,
|
find: /^.*VPSwitchAppearance\.vue$/,
|
||||||
replacement: fileURLToPath(
|
replacement: fileURLToPath(
|
||||||
new URL("./theme/components/CustomSwitchAppearance.vue", import.meta.url),
|
new URL('./theme/components/CustomSwitchAppearance.vue', import.meta.url),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
plugins: [ElementPlus({})],
|
plugins: [ElementPlus({})],
|
||||||
ssr: {
|
ssr: {
|
||||||
noExternal: ["element-plus"],
|
noExternal: ['element-plus'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
export const GITHUB_EXTENSION_JSON
|
export const GITHUB_EXTENSION_JSON
|
||||||
= "https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/index.json"
|
= 'https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/index.json'
|
||||||
export const GITHUB_STABLE_API = "https://api.github.com/repos/tachiyomiorg/tachiyomi/releases/latest"
|
export const GITHUB_STABLE_API = 'https://api.github.com/repos/tachiyomiorg/tachiyomi/releases/latest'
|
||||||
export const GITHUB_STABLE_RELEASE = "https://github.com/tachiyomiorg/tachiyomi/releases/latest"
|
export const GITHUB_STABLE_RELEASE = 'https://github.com/tachiyomiorg/tachiyomi/releases/latest'
|
||||||
export const GITHUB_PREVIEW_API = "https://api.github.com/repos/tachiyomiorg/android-app-preview/releases/latest"
|
export const GITHUB_PREVIEW_API = 'https://api.github.com/repos/tachiyomiorg/android-app-preview/releases/latest'
|
||||||
export const GITHUB_PREVIEW_RELEASE = "https://github.com/tachiyomiorg/android-app-preview/releases/latest"
|
export const GITHUB_PREVIEW_RELEASE = 'https://github.com/tachiyomiorg/android-app-preview/releases/latest'
|
||||||
|
@ -1,59 +1,59 @@
|
|||||||
import type { HeadConfig } from "vitepress"
|
import type { HeadConfig } from 'vitepress'
|
||||||
|
|
||||||
const headConfig: HeadConfig[] = [
|
const headConfig: HeadConfig[] = [
|
||||||
["meta", { name: "darkreader-lock" }],
|
['meta', { name: 'darkreader-lock' }],
|
||||||
|
|
||||||
["meta", { name: "theme-color", content: "#818CF8" }],
|
['meta', { name: 'theme-color', content: '#818CF8' }],
|
||||||
["meta", { name: "msapplication-TileColor", content: "#818CF8" }],
|
['meta', { name: 'msapplication-TileColor', content: '#818CF8' }],
|
||||||
|
|
||||||
["meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }],
|
['meta', { name: 'viewport', content: 'width=device-width, initial-scale=1.0' }],
|
||||||
["meta", { name: "referrer", content: "no-referrer-when-downgrade" }],
|
['meta', { name: 'referrer', content: 'no-referrer-when-downgrade' }],
|
||||||
|
|
||||||
["link", { rel: "icon", type: "image/x-icon", href: "/favicon.ico" }],
|
['link', { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
|
||||||
[
|
[
|
||||||
"link",
|
'link',
|
||||||
{
|
{
|
||||||
rel: "icon",
|
rel: 'icon',
|
||||||
type: "image/png",
|
type: 'image/png',
|
||||||
sizes: "32x32",
|
sizes: '32x32',
|
||||||
href: "/favicon-32x32.png",
|
href: '/favicon-32x32.png',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"link",
|
'link',
|
||||||
{
|
{
|
||||||
rel: "icon",
|
rel: 'icon',
|
||||||
type: "image/png",
|
type: 'image/png',
|
||||||
sizes: "16x16",
|
sizes: '16x16',
|
||||||
href: "/favicon-16x16.png",
|
href: '/favicon-16x16.png',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
["link", { rel: "manifest", href: "/site.webmanifest" }],
|
['link', { rel: 'manifest', href: '/site.webmanifest' }],
|
||||||
["link", { rel: "mask-icon", href: "/safari-pinned-tab.svg", color: "#818CF8" }],
|
['link', { rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#818CF8' }],
|
||||||
[
|
[
|
||||||
"link",
|
'link',
|
||||||
{
|
{
|
||||||
rel: "apple-touch-icon",
|
rel: 'apple-touch-icon',
|
||||||
type: "image/x-icon",
|
type: 'image/x-icon',
|
||||||
sizes: "180x180",
|
sizes: '180x180',
|
||||||
href: "/favicon.ico",
|
href: '/favicon.ico',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
["meta", { name: "twitter:card", content: "summary" }],
|
['meta', { name: 'twitter:card', content: 'summary' }],
|
||||||
["meta", { name: "twitter:site", content: "@tachiyomiorg" }],
|
['meta', { name: 'twitter:site', content: '@tachiyomiorg' }],
|
||||||
["meta", { name: "twitter:creator", content: "@tachiyomiorg" }],
|
['meta', { name: 'twitter:creator', content: '@tachiyomiorg' }],
|
||||||
|
|
||||||
["meta", { property: "og:site_name", content: "Tachiyomi" }],
|
['meta', { property: 'og:site_name', content: 'Tachiyomi' }],
|
||||||
[
|
[
|
||||||
"meta",
|
'meta',
|
||||||
{
|
{
|
||||||
property: "og:description",
|
property: 'og:description',
|
||||||
content: "Discover and read manga, webtoons, comics, and more – easier than ever on your Android device.",
|
content: 'Discover and read manga, webtoons, comics, and more – easier than ever on your Android device.',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
["meta", { property: "og:locale", content: "en_US" }],
|
['meta', { property: 'og:locale', content: 'en_US' }],
|
||||||
["meta", { property: "og:type", content: "website" }],
|
['meta', { property: 'og:type', content: 'website' }],
|
||||||
]
|
]
|
||||||
|
|
||||||
export default headConfig
|
export default headConfig
|
||||||
|
@ -1,61 +1,61 @@
|
|||||||
import path from "node:path"
|
import path from 'node:path'
|
||||||
import { writeFileSync } from "node:fs"
|
import { writeFileSync } from 'node:fs'
|
||||||
import { Feed, type Item } from "feed"
|
import { Feed, type Item } from 'feed'
|
||||||
import { type SiteConfig, createContentLoader } from "vitepress"
|
import { type SiteConfig, createContentLoader } from 'vitepress'
|
||||||
|
|
||||||
async function generateFeed(config: SiteConfig, hostname: string) {
|
async function generateFeed(config: SiteConfig, hostname: string) {
|
||||||
const feed = new Feed({
|
const feed = new Feed({
|
||||||
title: config.site.title,
|
title: config.site.title,
|
||||||
description: config.site.description,
|
description: config.site.description,
|
||||||
id: hostname,
|
id: hostname,
|
||||||
link: hostname,
|
link: hostname,
|
||||||
language: "en",
|
language: 'en',
|
||||||
image: `${hostname}/img/logo.png`,
|
image: `${hostname}/img/logo.png`,
|
||||||
favicon: `${hostname}/favicon.ico`,
|
favicon: `${hostname}/favicon.ico`,
|
||||||
copyright: `Copyright © 2015 - ${new Date().getFullYear()} Javier Tomás`,
|
copyright: `Copyright © 2015 - ${new Date().getFullYear()} Javier Tomás`,
|
||||||
})
|
})
|
||||||
const json: Item[] = []
|
const json: Item[] = []
|
||||||
|
|
||||||
const posts = await createContentLoader("news/*.md", {
|
const posts = await createContentLoader('news/*.md', {
|
||||||
excerpt: true,
|
excerpt: true,
|
||||||
render: true,
|
render: true,
|
||||||
includeSrc: true,
|
includeSrc: true,
|
||||||
}).load()
|
}).load()
|
||||||
|
|
||||||
// Filter everything that"s not of type `article` (e.g. index.md)
|
// Filter everything that"s not of type `article` (e.g. index.md)
|
||||||
const filteredPosts = posts.filter((post) => post.frontmatter.type === "article")
|
const filteredPosts = posts.filter(post => post.frontmatter.type === 'article')
|
||||||
|
|
||||||
filteredPosts.sort((a, b) => +new Date(b.frontmatter.date as string) - +new Date(a.frontmatter.date as string))
|
filteredPosts.sort((a, b) => +new Date(b.frontmatter.date as string) - +new Date(a.frontmatter.date as string))
|
||||||
|
|
||||||
for (const { url, frontmatter, html, src } of filteredPosts) {
|
for (const { url, frontmatter, html, src } of filteredPosts) {
|
||||||
const fullUrl = `${hostname}${url}`
|
const fullUrl = `${hostname}${url}`
|
||||||
|
|
||||||
// Strip `​` from `html` string
|
// Strip `​` from `html` string
|
||||||
const content = (html ?? "")
|
const content = (html ?? '')
|
||||||
.replace(/​/g, "")
|
.replace(/​/g, '')
|
||||||
.replace(/<a href="(\/.*?)">/g, `<a href="${hostname}$1">`)
|
.replace(/<a href="(\/.*?)">/g, `<a href="${hostname}$1">`)
|
||||||
|
|
||||||
const markdown = (src ?? "")
|
const markdown = (src ?? '')
|
||||||
.replace(/^---.*---/s, "")
|
.replace(/^---.*---/s, '')
|
||||||
.replace(/]\((\/.*?)\)/g, `](${hostname}$1)`)
|
.replace(/]\((\/.*?)\)/g, `](${hostname}$1)`)
|
||||||
.replace(/^# .*$/m, "")
|
.replace(/^# .*$/m, '')
|
||||||
.trim()
|
.trim()
|
||||||
|
|
||||||
const post = {
|
const post = {
|
||||||
title: frontmatter.title,
|
title: frontmatter.title,
|
||||||
id: fullUrl,
|
id: fullUrl,
|
||||||
link: fullUrl,
|
link: fullUrl,
|
||||||
description: frontmatter.description,
|
description: frontmatter.description,
|
||||||
content,
|
content,
|
||||||
date: frontmatter.date,
|
date: frontmatter.date,
|
||||||
} satisfies Item
|
} satisfies Item
|
||||||
|
|
||||||
feed.addItem(post)
|
feed.addItem(post)
|
||||||
json.push({ ...post, content: markdown })
|
json.push({ ...post, content: markdown })
|
||||||
}
|
}
|
||||||
|
|
||||||
writeFileSync(path.join(config.outDir, "feed.rss"), feed.rss2())
|
writeFileSync(path.join(config.outDir, 'feed.rss'), feed.rss2())
|
||||||
writeFileSync(path.join(config.outDir, "news.json"), JSON.stringify(json))
|
writeFileSync(path.join(config.outDir, 'news.json'), JSON.stringify(json))
|
||||||
}
|
}
|
||||||
|
|
||||||
export default generateFeed
|
export default generateFeed
|
||||||
|
@ -1,131 +1,133 @@
|
|||||||
import type { HeadConfig, TransformContext } from "vitepress"
|
import type { HeadConfig, TransformContext } from 'vitepress'
|
||||||
|
|
||||||
function generateMeta(context: TransformContext, hostname: string) {
|
function generateMeta(context: TransformContext, hostname: string) {
|
||||||
const head: HeadConfig[] = []
|
const head: HeadConfig[] = []
|
||||||
const { pageData } = context
|
const { pageData } = context
|
||||||
|
|
||||||
const url = `${hostname}/${pageData.relativePath.replace(/((^|\/)index)?\.md$/, "$2")}`
|
const url = `${hostname}/${pageData.relativePath.replace(/((^|\/)index)?\.md$/, '$2')}`
|
||||||
|
|
||||||
head.push(["link", { rel: "canonical", href: url }])
|
head.push(['link', { rel: 'canonical', href: url }])
|
||||||
head.push(["meta", { property: "og:url", content: url }])
|
head.push(['meta', { property: 'og:url', content: url }])
|
||||||
head.push(["meta", { name: "twitter:url", content: url }])
|
head.push(['meta', { name: 'twitter:url', content: url }])
|
||||||
head.push(["meta", { name: "twitter:card", content: "summary_large_image" }])
|
head.push(['meta', { name: 'twitter:card', content: 'summary_large_image' }])
|
||||||
|
|
||||||
if (pageData.frontmatter.theme) {
|
if (pageData.frontmatter.theme)
|
||||||
head.push(["meta", { name: "theme-color", content: pageData.frontmatter.theme }])
|
head.push(['meta', { name: 'theme-color', content: pageData.frontmatter.theme }])
|
||||||
}
|
|
||||||
if (pageData.frontmatter.type) {
|
|
||||||
head.push(["meta", { property: "og:type", content: pageData.frontmatter.type }])
|
|
||||||
}
|
|
||||||
if (pageData.frontmatter.customMetaTitle) {
|
|
||||||
head.push([
|
|
||||||
"meta",
|
|
||||||
{
|
|
||||||
property: "og:title",
|
|
||||||
content: pageData.frontmatter.customMetaTitle,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
head.push([
|
|
||||||
"meta",
|
|
||||||
{
|
|
||||||
name: "twitter:title",
|
|
||||||
content: pageData.frontmatter.customMetaTitle,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
head.push(["meta", { property: "og:site_name", content: "" }])
|
|
||||||
} else {
|
|
||||||
head.push(["meta", { property: "og:title", content: pageData.frontmatter.title }])
|
|
||||||
head.push(["meta", { name: "twitter:title", content: pageData.frontmatter.title }])
|
|
||||||
}
|
|
||||||
if (pageData.frontmatter.description) {
|
|
||||||
head.push([
|
|
||||||
"meta",
|
|
||||||
{
|
|
||||||
property: "og:description",
|
|
||||||
content: pageData.frontmatter.description,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
head.push([
|
|
||||||
"meta",
|
|
||||||
{
|
|
||||||
name: "twitter:description",
|
|
||||||
content: pageData.frontmatter.description,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
}
|
|
||||||
if (pageData.frontmatter.image) {
|
|
||||||
head.push([
|
|
||||||
"meta",
|
|
||||||
{
|
|
||||||
property: "og:image",
|
|
||||||
content: `${hostname}/${pageData.frontmatter.image.replace(/^\//, "")}`,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
head.push([
|
|
||||||
"meta",
|
|
||||||
{
|
|
||||||
name: "twitter:image",
|
|
||||||
content: `${hostname}/${pageData.frontmatter.image.replace(/^\//, "")}`,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
} else {
|
|
||||||
const url = pageData.filePath.replace("index.md", "").replace(".md", "")
|
|
||||||
const imageUrl = `${url}/__og_image__/og.png`.replace(/\/\//g, "/").replace(/^\//, "")
|
|
||||||
|
|
||||||
head.push(["meta", { property: "og:image", content: `${hostname}/${imageUrl}` }])
|
if (pageData.frontmatter.type)
|
||||||
head.push(["meta", { property: "og:image:width", content: "1200" }])
|
head.push(['meta', { property: 'og:type', content: pageData.frontmatter.type }])
|
||||||
head.push(["meta", { property: "og:image:height", content: "628" }])
|
|
||||||
head.push(["meta", { property: "og:image:type", content: "image/png" }])
|
|
||||||
head.push(["meta", { property: "og:image:alt", content: pageData.frontmatter.title }])
|
|
||||||
head.push(["meta", { name: "twitter:image", content: `${hostname}/${imageUrl}` }])
|
|
||||||
head.push(["meta", { name: "twitter:image:width", content: "1200" }])
|
|
||||||
head.push(["meta", { name: "twitter:image:height", content: "628" }])
|
|
||||||
head.push(["meta", { name: "twitter:image:alt", content: pageData.frontmatter.title }])
|
|
||||||
}
|
|
||||||
if (pageData.frontmatter.tag) {
|
|
||||||
head.push(["meta", { property: "article:tag", content: pageData.frontmatter.tag }])
|
|
||||||
}
|
|
||||||
if (pageData.frontmatter.date) {
|
|
||||||
head.push([
|
|
||||||
"meta",
|
|
||||||
{
|
|
||||||
property: "article:published_time",
|
|
||||||
content: pageData.frontmatter.date,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
}
|
|
||||||
if (pageData.lastUpdated && pageData.frontmatter.lastUpdated !== false) {
|
|
||||||
head.push([
|
|
||||||
"meta",
|
|
||||||
{
|
|
||||||
property: "article:modified_time",
|
|
||||||
content: new Date(pageData.lastUpdated).toISOString(),
|
|
||||||
},
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pageData.filePath === "news/index.md") {
|
if (pageData.frontmatter.customMetaTitle) {
|
||||||
head.push([
|
head.push([
|
||||||
"link",
|
'meta',
|
||||||
{
|
{
|
||||||
rel: "alternate",
|
property: 'og:title',
|
||||||
type: "application/rss+xml",
|
content: pageData.frontmatter.customMetaTitle,
|
||||||
title: "RSS feed for the news archive",
|
},
|
||||||
href: `${hostname}/feed.rss`,
|
])
|
||||||
},
|
head.push([
|
||||||
])
|
'meta',
|
||||||
head.push([
|
{
|
||||||
"link",
|
name: 'twitter:title',
|
||||||
{
|
content: pageData.frontmatter.customMetaTitle,
|
||||||
rel: "alternate",
|
},
|
||||||
type: "application/json",
|
])
|
||||||
title: "JSON of the news archive",
|
head.push(['meta', { property: 'og:site_name', content: '' }])
|
||||||
href: `${hostname}/news.json`,
|
}
|
||||||
},
|
else {
|
||||||
])
|
head.push(['meta', { property: 'og:title', content: pageData.frontmatter.title }])
|
||||||
}
|
head.push(['meta', { name: 'twitter:title', content: pageData.frontmatter.title }])
|
||||||
|
}
|
||||||
|
if (pageData.frontmatter.description) {
|
||||||
|
head.push([
|
||||||
|
'meta',
|
||||||
|
{
|
||||||
|
property: 'og:description',
|
||||||
|
content: pageData.frontmatter.description,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
head.push([
|
||||||
|
'meta',
|
||||||
|
{
|
||||||
|
name: 'twitter:description',
|
||||||
|
content: pageData.frontmatter.description,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
if (pageData.frontmatter.image) {
|
||||||
|
head.push([
|
||||||
|
'meta',
|
||||||
|
{
|
||||||
|
property: 'og:image',
|
||||||
|
content: `${hostname}/${pageData.frontmatter.image.replace(/^\//, '')}`,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
head.push([
|
||||||
|
'meta',
|
||||||
|
{
|
||||||
|
name: 'twitter:image',
|
||||||
|
content: `${hostname}/${pageData.frontmatter.image.replace(/^\//, '')}`,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const url = pageData.filePath.replace('index.md', '').replace('.md', '')
|
||||||
|
const imageUrl = `${url}/__og_image__/og.png`.replace(/\/\//g, '/').replace(/^\//, '')
|
||||||
|
|
||||||
return head
|
head.push(['meta', { property: 'og:image', content: `${hostname}/${imageUrl}` }])
|
||||||
|
head.push(['meta', { property: 'og:image:width', content: '1200' }])
|
||||||
|
head.push(['meta', { property: 'og:image:height', content: '628' }])
|
||||||
|
head.push(['meta', { property: 'og:image:type', content: 'image/png' }])
|
||||||
|
head.push(['meta', { property: 'og:image:alt', content: pageData.frontmatter.title }])
|
||||||
|
head.push(['meta', { name: 'twitter:image', content: `${hostname}/${imageUrl}` }])
|
||||||
|
head.push(['meta', { name: 'twitter:image:width', content: '1200' }])
|
||||||
|
head.push(['meta', { name: 'twitter:image:height', content: '628' }])
|
||||||
|
head.push(['meta', { name: 'twitter:image:alt', content: pageData.frontmatter.title }])
|
||||||
|
}
|
||||||
|
if (pageData.frontmatter.tag)
|
||||||
|
head.push(['meta', { property: 'article:tag', content: pageData.frontmatter.tag }])
|
||||||
|
|
||||||
|
if (pageData.frontmatter.date) {
|
||||||
|
head.push([
|
||||||
|
'meta',
|
||||||
|
{
|
||||||
|
property: 'article:published_time',
|
||||||
|
content: pageData.frontmatter.date,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
if (pageData.lastUpdated && pageData.frontmatter.lastUpdated !== false) {
|
||||||
|
head.push([
|
||||||
|
'meta',
|
||||||
|
{
|
||||||
|
property: 'article:modified_time',
|
||||||
|
content: new Date(pageData.lastUpdated).toISOString(),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageData.filePath === 'news/index.md') {
|
||||||
|
head.push([
|
||||||
|
'link',
|
||||||
|
{
|
||||||
|
rel: 'alternate',
|
||||||
|
type: 'application/rss+xml',
|
||||||
|
title: 'RSS feed for the news archive',
|
||||||
|
href: `${hostname}/feed.rss`,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
head.push([
|
||||||
|
'link',
|
||||||
|
{
|
||||||
|
rel: 'alternate',
|
||||||
|
type: 'application/json',
|
||||||
|
title: 'JSON of the news archive',
|
||||||
|
href: `${hostname}/news.json`,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
return head
|
||||||
}
|
}
|
||||||
|
|
||||||
export default generateMeta
|
export default generateMeta
|
||||||
|
@ -1,111 +1,110 @@
|
|||||||
import { mkdir, readFile, writeFile } from "node:fs/promises"
|
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
||||||
import { dirname, resolve } from "node:path"
|
import { dirname, resolve } from 'node:path'
|
||||||
import { fileURLToPath } from "node:url"
|
import { fileURLToPath } from 'node:url'
|
||||||
import { createContentLoader } from "vitepress"
|
import { createContentLoader } from 'vitepress'
|
||||||
import type { ContentData, SiteConfig } from "vitepress"
|
import type { ContentData, SiteConfig } from 'vitepress'
|
||||||
import { type SatoriOptions, satoriVue } from "x-satori/vue"
|
import { type SatoriOptions, satoriVue } from 'x-satori/vue'
|
||||||
import { renderAsync } from "@resvg/resvg-js"
|
import { renderAsync } from '@resvg/resvg-js'
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
const __fonts = resolve(__dirname, "../../fonts")
|
const __fonts = resolve(__dirname, '../../fonts')
|
||||||
|
|
||||||
async function generateOgImages(config: SiteConfig) {
|
async function generateOgImages(config: SiteConfig) {
|
||||||
const pages = await createContentLoader("**/*.md", { excerpt: true }).load()
|
const pages = await createContentLoader('**/*.md', { excerpt: true }).load()
|
||||||
const template = await readFile(resolve(__dirname, "../../theme/components/OgImageTemplate.vue"), "utf-8")
|
const template = await readFile(resolve(__dirname, '../../theme/components/OgImageTemplate.vue'), 'utf-8')
|
||||||
|
|
||||||
const fonts: SatoriOptions["fonts"] = [
|
const fonts: SatoriOptions['fonts'] = [
|
||||||
{
|
{
|
||||||
name: "Inter",
|
name: 'Inter',
|
||||||
data: await readFile(resolve(__fonts, "Inter-Regular.otf")),
|
data: await readFile(resolve(__fonts, 'Inter-Regular.otf')),
|
||||||
weight: 400,
|
weight: 400,
|
||||||
style: "normal",
|
style: 'normal',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Inter",
|
name: 'Inter',
|
||||||
data: await readFile(resolve(__fonts, "Inter-Medium.otf")),
|
data: await readFile(resolve(__fonts, 'Inter-Medium.otf')),
|
||||||
weight: 500,
|
weight: 500,
|
||||||
style: "normal",
|
style: 'normal',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Inter",
|
name: 'Inter',
|
||||||
data: await readFile(resolve(__fonts, "Inter-SemiBold.otf")),
|
data: await readFile(resolve(__fonts, 'Inter-SemiBold.otf')),
|
||||||
weight: 600,
|
weight: 600,
|
||||||
style: "normal",
|
style: 'normal',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Inter",
|
name: 'Inter',
|
||||||
data: await readFile(resolve(__fonts, "Inter-Bold.otf")),
|
data: await readFile(resolve(__fonts, 'Inter-Bold.otf')),
|
||||||
weight: 700,
|
weight: 700,
|
||||||
style: "normal",
|
style: 'normal',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const filteredPages = pages.filter((p) => p.frontmatter.image === undefined)
|
const filteredPages = pages.filter(p => p.frontmatter.image === undefined)
|
||||||
|
|
||||||
for (const page of filteredPages) {
|
for (const page of filteredPages) {
|
||||||
await generateImage({
|
await generateImage({
|
||||||
page,
|
page,
|
||||||
template,
|
template,
|
||||||
outDir: config.outDir,
|
outDir: config.outDir,
|
||||||
fonts,
|
fonts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default generateOgImages
|
export default generateOgImages
|
||||||
|
|
||||||
interface GenerateImagesOptions {
|
interface GenerateImagesOptions {
|
||||||
page: ContentData
|
page: ContentData
|
||||||
template: string
|
template: string
|
||||||
outDir: string
|
outDir: string
|
||||||
fonts: SatoriOptions["fonts"]
|
fonts: SatoriOptions['fonts']
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDir(url: string) {
|
function getDir(url: string) {
|
||||||
if (url.startsWith("/docs/faq/")) {
|
if (url.startsWith('/docs/faq/'))
|
||||||
return "FAQ"
|
return 'FAQ'
|
||||||
} else if (url.startsWith("/docs/guides/")) {
|
else if (url.startsWith('/docs/guides/'))
|
||||||
return "Guide"
|
return 'Guide'
|
||||||
} else if (url.startsWith("/news/") && url !== "/news/") {
|
else if (url.startsWith('/news/') && url !== '/news/')
|
||||||
return "News"
|
return 'News'
|
||||||
}
|
|
||||||
|
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateImage({ page, template, outDir, fonts }: GenerateImagesOptions) {
|
async function generateImage({ page, template, outDir, fonts }: GenerateImagesOptions) {
|
||||||
const { frontmatter, url } = page
|
const { frontmatter, url } = page
|
||||||
|
|
||||||
const options: SatoriOptions = {
|
const options: SatoriOptions = {
|
||||||
width: 1200,
|
width: 1200,
|
||||||
height: 628,
|
height: 628,
|
||||||
fonts,
|
fonts,
|
||||||
props: {
|
props: {
|
||||||
title:
|
title:
|
||||||
frontmatter.layout === "home"
|
frontmatter.layout === 'home'
|
||||||
? frontmatter.hero.name ?? frontmatter.title
|
? frontmatter.hero.name ?? frontmatter.title
|
||||||
: frontmatter.customMetaTitle ?? frontmatter.title,
|
: frontmatter.customMetaTitle ?? frontmatter.title,
|
||||||
description:
|
description:
|
||||||
frontmatter.layout === "home"
|
frontmatter.layout === 'home'
|
||||||
? frontmatter.hero.tagline ?? frontmatter.description
|
? frontmatter.hero.tagline ?? frontmatter.description
|
||||||
: frontmatter.description,
|
: frontmatter.description,
|
||||||
dir: getDir(url),
|
dir: getDir(url),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const svg = await satoriVue(options, template)
|
const svg = await satoriVue(options, template)
|
||||||
|
|
||||||
const render = await renderAsync(svg, {
|
const render = await renderAsync(svg, {
|
||||||
fitTo: {
|
fitTo: {
|
||||||
mode: "width",
|
mode: 'width',
|
||||||
value: 1200,
|
value: 1200,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const outputFolder = resolve(outDir, url.substring(1), "__og_image__")
|
const outputFolder = resolve(outDir, url.substring(1), '__og_image__')
|
||||||
const outputFile = resolve(outputFolder, "og.png")
|
const outputFile = resolve(outputFolder, 'og.png')
|
||||||
|
|
||||||
await mkdir(outputFolder, { recursive: true })
|
await mkdir(outputFolder, { recursive: true })
|
||||||
|
|
||||||
return await writeFile(outputFile, render.asPng())
|
return await writeFile(outputFile, render.asPng())
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
import type { MarkdownOptions } from "vitepress"
|
import type { MarkdownOptions } from 'vitepress'
|
||||||
|
|
||||||
import { attrs } from "@mdit/plugin-attrs"
|
import { attrs } from '@mdit/plugin-attrs'
|
||||||
import { figure } from "@mdit/plugin-figure"
|
import { figure } from '@mdit/plugin-figure'
|
||||||
import { imgLazyload } from "@mdit/plugin-img-lazyload"
|
import { imgLazyload } from '@mdit/plugin-img-lazyload'
|
||||||
import { imgMark } from "@mdit/plugin-img-mark"
|
import { imgMark } from '@mdit/plugin-img-mark'
|
||||||
import { imgSize } from "@mdit/plugin-img-size"
|
import { imgSize } from '@mdit/plugin-img-size'
|
||||||
import { include } from "@mdit/plugin-include"
|
import { include } from '@mdit/plugin-include'
|
||||||
import { tabsMarkdownPlugin } from "vitepress-plugin-tabs"
|
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
|
||||||
import shortcode_plugin from "markdown-it-shortcode-tag"
|
import shortcode_plugin from 'markdown-it-shortcode-tag'
|
||||||
import shortcodes from "./shortcodes"
|
import shortcodes from './shortcodes'
|
||||||
|
|
||||||
const markdownConfig: MarkdownOptions = {
|
const markdownConfig: MarkdownOptions = {
|
||||||
config: (md) => {
|
config: (md) => {
|
||||||
md
|
md
|
||||||
.use(attrs)
|
.use(attrs)
|
||||||
.use(figure)
|
.use(figure)
|
||||||
.use(imgLazyload)
|
.use(imgLazyload)
|
||||||
.use(imgMark)
|
.use(imgMark)
|
||||||
.use(imgSize)
|
.use(imgSize)
|
||||||
.use(include, {
|
.use(include, {
|
||||||
currentPath: (env) => env.filePath,
|
currentPath: env => env.filePath,
|
||||||
})
|
})
|
||||||
.use(tabsMarkdownPlugin)
|
.use(tabsMarkdownPlugin)
|
||||||
.use(shortcode_plugin, shortcodes)
|
.use(shortcode_plugin, shortcodes)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default markdownConfig
|
export default markdownConfig
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
import type { DefaultTheme } from "vitepress"
|
import type { DefaultTheme } from 'vitepress'
|
||||||
|
|
||||||
const nav: DefaultTheme.NavItem[] = [
|
const nav: DefaultTheme.NavItem[] = [
|
||||||
{
|
{
|
||||||
text: "Get v{app_version}",
|
text: 'Get v{app_version}',
|
||||||
activeMatch: "^/*?(download|changelogs)/*?$",
|
activeMatch: '^/*?(download|changelogs)/*?$',
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
text: "Download",
|
text: 'Download',
|
||||||
link: "/download/",
|
link: '/download/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Changelogs",
|
text: 'Changelogs',
|
||||||
link: "/changelogs/",
|
link: '/changelogs/',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Docs",
|
text: 'Docs',
|
||||||
link: "/docs/guides/getting-started",
|
link: '/docs/guides/getting-started',
|
||||||
activeMatch: "/docs/",
|
activeMatch: '/docs/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "News",
|
text: 'News',
|
||||||
link: "/news/",
|
link: '/news/',
|
||||||
activeMatch: "/news/",
|
activeMatch: '/news/',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export default nav
|
export default nav
|
||||||
|
@ -1,130 +1,130 @@
|
|||||||
import type { DefaultTheme } from "vitepress"
|
import type { DefaultTheme } from 'vitepress'
|
||||||
|
|
||||||
const sidebar: DefaultTheme.SidebarMulti = {
|
const sidebar: DefaultTheme.SidebarMulti = {
|
||||||
"/download/": defaultSidebar(),
|
'/download/': defaultSidebar(),
|
||||||
"/extensions/": defaultSidebar(),
|
'/extensions/': defaultSidebar(),
|
||||||
"/docs/": defaultSidebar(),
|
'/docs/': defaultSidebar(),
|
||||||
"/forks/": defaultSidebar(),
|
'/forks/': defaultSidebar(),
|
||||||
"/changelogs/": defaultSidebar(),
|
'/changelogs/': defaultSidebar(),
|
||||||
"/news/": defaultSidebar(),
|
'/news/': defaultSidebar(),
|
||||||
"/sandbox/": defaultSidebar(),
|
'/sandbox/': defaultSidebar(),
|
||||||
}
|
}
|
||||||
|
|
||||||
function defaultSidebar(): DefaultTheme.SidebarItem[] {
|
function defaultSidebar(): DefaultTheme.SidebarItem[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
text: "Download",
|
text: 'Download',
|
||||||
link: "/download/",
|
link: '/download/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Extensions",
|
text: 'Extensions',
|
||||||
link: "/extensions/",
|
link: '/extensions/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Changelogs",
|
text: 'Changelogs',
|
||||||
link: "/changelogs/",
|
link: '/changelogs/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Forks",
|
text: 'Forks',
|
||||||
link: "/forks/",
|
link: '/forks/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Contribute",
|
text: 'Contribute',
|
||||||
link: "/docs/contribute",
|
link: '/docs/contribute',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Frequently Asked Questions",
|
text: 'Frequently Asked Questions',
|
||||||
items: [
|
items: [
|
||||||
{ text: "General", link: "/docs/faq/general" },
|
{ text: 'General', link: '/docs/faq/general' },
|
||||||
{
|
{
|
||||||
text: "Library",
|
text: 'Library',
|
||||||
link: "/docs/faq/library",
|
link: '/docs/faq/library',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Browse",
|
text: 'Browse',
|
||||||
link: "/docs/faq/browse/",
|
link: '/docs/faq/browse/',
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
items: [
|
items: [
|
||||||
{ text: "Extensions", link: "/docs/faq/browse/extensions" },
|
{ text: 'Extensions', link: '/docs/faq/browse/extensions' },
|
||||||
{
|
{
|
||||||
text: "Local source",
|
text: 'Local source',
|
||||||
link: "/docs/faq/browse/local-source",
|
link: '/docs/faq/browse/local-source',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Downloads",
|
text: 'Downloads',
|
||||||
link: "/docs/faq/downloads",
|
link: '/docs/faq/downloads',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Reader",
|
text: 'Reader',
|
||||||
link: "/docs/faq/reader",
|
link: '/docs/faq/reader',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Settings",
|
text: 'Settings',
|
||||||
link: "/docs/faq/settings",
|
link: '/docs/faq/settings',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Android 11+",
|
text: 'Android 11+',
|
||||||
link: "/docs/faq/android-11+",
|
link: '/docs/faq/android-11+',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Guides",
|
text: 'Guides',
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
text: "Getting started",
|
text: 'Getting started',
|
||||||
link: "/docs/guides/getting-started",
|
link: '/docs/guides/getting-started',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Troubleshooting",
|
text: 'Troubleshooting',
|
||||||
link: "/docs/guides/troubleshooting/",
|
link: '/docs/guides/troubleshooting/',
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
text: "Common issues",
|
text: 'Common issues',
|
||||||
link: "/docs/guides/troubleshooting/common-issues",
|
link: '/docs/guides/troubleshooting/common-issues',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Diagnosis",
|
text: 'Diagnosis',
|
||||||
link: "/docs/guides/troubleshooting/diagnosis",
|
link: '/docs/guides/troubleshooting/diagnosis',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Source migration",
|
text: 'Source migration',
|
||||||
link: "/docs/guides/source-migration",
|
link: '/docs/guides/source-migration',
|
||||||
},
|
},
|
||||||
{ text: "Backups", link: "/docs/guides/backups" },
|
{ text: 'Backups', link: '/docs/guides/backups' },
|
||||||
{ text: "Tracking", link: "/docs/guides/tracking" },
|
{ text: 'Tracking', link: '/docs/guides/tracking' },
|
||||||
{ text: "Categories", link: "/docs/guides/categories" },
|
{ text: 'Categories', link: '/docs/guides/categories' },
|
||||||
{
|
{
|
||||||
text: "Local source",
|
text: 'Local source',
|
||||||
link: "/docs/guides/local-source/",
|
link: '/docs/guides/local-source/',
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
text: "Advanced editing",
|
text: 'Advanced editing',
|
||||||
link: "/docs/guides/local-source/advanced",
|
link: '/docs/guides/local-source/advanced',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Reader settings",
|
text: 'Reader settings',
|
||||||
link: "/docs/guides/reader-settings",
|
link: '/docs/guides/reader-settings',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Shizuku",
|
text: 'Shizuku',
|
||||||
link: "/docs/guides/shizuku",
|
link: '/docs/guides/shizuku',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default sidebar
|
export default sidebar
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
export function simpleLangName(code: string) {
|
export function simpleLangName(code: string) {
|
||||||
if (code === "all") {
|
if (code === 'all')
|
||||||
return "All"
|
return 'All'
|
||||||
}
|
|
||||||
const namesInEnglish = new Intl.DisplayNames(["en"], { type: "language" })
|
const namesInEnglish = new Intl.DisplayNames(['en'], { type: 'language' })
|
||||||
return capitalize(namesInEnglish.of(code)!, "en")
|
return capitalize(namesInEnglish.of(code)!, 'en')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function langName(code: string) {
|
export function langName(code: string) {
|
||||||
if (code === "all") {
|
if (code === 'all')
|
||||||
return "All"
|
return 'All'
|
||||||
}
|
|
||||||
|
|
||||||
const namesInEnglish = new Intl.DisplayNames(["en"], { type: "language" })
|
const namesInEnglish = new Intl.DisplayNames(['en'], { type: 'language' })
|
||||||
const namesInNative = new Intl.DisplayNames([code], { type: "language" })
|
const namesInNative = new Intl.DisplayNames([code], { type: 'language' })
|
||||||
return `${capitalize(namesInEnglish.of(code)!, "en")} - ${capitalize(namesInNative.of(code)!, code)}`
|
return `${capitalize(namesInEnglish.of(code)!, 'en')} - ${capitalize(namesInNative.of(code)!, code)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function capitalize(string: string, locale: string) {
|
function capitalize(string: string, locale: string) {
|
||||||
return string.charAt(0).toLocaleUpperCase(locale) + string.substring(1)
|
return string.charAt(0).toLocaleUpperCase(locale) + string.substring(1)
|
||||||
}
|
}
|
||||||
|
@ -1,91 +1,89 @@
|
|||||||
const iconMappings = {
|
const iconMappings = {
|
||||||
alertDecagramOutline: '<svg originalIcon="alertDecagramOutline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23,12L20.56,14.78L20.9,18.46L17.29,19.28L15.4,22.46L12,21L8.6,22.47L6.71,19.29L3.1,18.47L3.44,14.78L1,12L3.44,9.21L3.1,5.53L6.71,4.72L8.6,1.54L12,3L15.4,1.54L17.29,4.72L20.9,5.54L20.56,9.22L23,12M20.33,12L18.5,9.89L18.74,7.1L16,6.5L14.58,4.07L12,5.18L9.42,4.07L8,6.5L5.26,7.09L5.5,9.88L3.67,12L5.5,14.1L5.26,16.9L8,17.5L9.42,19.93L12,18.81L14.58,19.92L16,17.5L18.74,16.89L18.5,14.1L20.33,12M11,15H13V17H11V15M11,7H13V13H11V7" /></svg>',
|
alertDecagramOutline: '<svg originalIcon="alertDecagramOutline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23,12L20.56,14.78L20.9,18.46L17.29,19.28L15.4,22.46L12,21L8.6,22.47L6.71,19.29L3.1,18.47L3.44,14.78L1,12L3.44,9.21L3.1,5.53L6.71,4.72L8.6,1.54L12,3L15.4,1.54L17.29,4.72L20.9,5.54L20.56,9.22L23,12M20.33,12L18.5,9.89L18.74,7.1L16,6.5L14.58,4.07L12,5.18L9.42,4.07L8,6.5L5.26,7.09L5.5,9.88L3.67,12L5.5,14.1L5.26,16.9L8,17.5L9.42,19.93L12,18.81L14.58,19.92L16,17.5L18.74,16.89L18.5,14.1L20.33,12M11,15H13V17H11V15M11,7H13V13H11V7" /></svg>',
|
||||||
backupRestore: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,3A9,9 0 0,0 3,12H0L4,16L8,12H5A7,7 0 0,1 12,5A7,7 0 0,1 19,12A7,7 0 0,1 12,19C10.5,19 9.09,18.5 7.94,17.7L6.5,19.14C8.04,20.3 9.94,21 12,21A9,9 0 0,0 21,12A9,9 0 0,0 12,3M14,12A2,2 0 0,0 12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12Z" /></svg>',
|
backupRestore: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,3A9,9 0 0,0 3,12H0L4,16L8,12H5A7,7 0 0,1 12,5A7,7 0 0,1 19,12A7,7 0 0,1 12,19C10.5,19 9.09,18.5 7.94,17.7L6.5,19.14C8.04,20.3 9.94,21 12,21A9,9 0 0,0 21,12A9,9 0 0,0 12,3M14,12A2,2 0 0,0 12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12Z" /></svg>',
|
||||||
bookmarkBoxOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 20H18V22H4C2.9 22 2 21.1 2 20V6H4V20M22 4V16C22 17.1 21.1 18 20 18H8C6.9 18 6 17.1 6 16V4C6 2.9 6.9 2 8 2H20C21.1 2 22 2.9 22 4M20 4H8V16H20V4M18 6H13V13L15.5 11.5L18 13V6Z" /></svg>',
|
bookmarkBoxOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 20H18V22H4C2.9 22 2 21.1 2 20V6H4V20M22 4V16C22 17.1 21.1 18 20 18H8C6.9 18 6 17.1 6 16V4C6 2.9 6.9 2 8 2H20C21.1 2 22 2.9 22 4M20 4H8V16H20V4M18 6H13V13L15.5 11.5L18 13V6Z" /></svg>',
|
||||||
bookOpenOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21,4H3A2,2 0 0,0 1,6V19A2,2 0 0,0 3,21H21A2,2 0 0,0 23,19V6A2,2 0 0,0 21,4M3,19V6H11V19H3M21,19H13V6H21V19M14,9.5H20V11H14V9.5M14,12H20V13.5H14V12M14,14.5H20V16H14V14.5Z" /></svg>',
|
bookOpenOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21,4H3A2,2 0 0,0 1,6V19A2,2 0 0,0 3,21H21A2,2 0 0,0 23,19V6A2,2 0 0,0 21,4M3,19V6H11V19H3M21,19H13V6H21V19M14,9.5H20V11H14V9.5M14,12H20V13.5H14V12M14,14.5H20V16H14V14.5Z" /></svg>',
|
||||||
cloudOffOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19.8 22.6L17.15 20H6.5Q4.2 20 2.6 18.4T1 14.5Q1 12.58 2.19 11.08 3.38 9.57 5.25 9.15 5.33 8.95 5.4 8.76 5.5 8.57 5.55 8.35L1.4 4.2L2.8 2.8L21.2 21.2M6.5 18H15.15L7.1 9.95Q7.05 10.23 7.03 10.5 7 10.73 7 11H6.5Q5.05 11 4.03 12.03 3 13.05 3 14.5 3 15.95 4.03 17 5.05 18 6.5 18M11.13 14M21.6 18.75L20.15 17.35Q20.58 17 20.79 16.54 21 16.08 21 15.5 21 14.45 20.27 13.73 19.55 13 18.5 13H17V11Q17 8.93 15.54 7.46 14.08 6 12 6 11.33 6 10.7 6.16 10.07 6.33 9.5 6.68L8.05 5.23Q8.93 4.63 9.91 4.31 10.9 4 12 4 14.93 4 16.96 6.04 19 8.07 19 11 20.73 11.2 21.86 12.5 23 13.78 23 15.5 23 16.5 22.63 17.31 22.25 18.15 21.6 18.75M14.83 12.03Z" /></svg>',
|
cloudOffOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19.8 22.6L17.15 20H6.5Q4.2 20 2.6 18.4T1 14.5Q1 12.58 2.19 11.08 3.38 9.57 5.25 9.15 5.33 8.95 5.4 8.76 5.5 8.57 5.55 8.35L1.4 4.2L2.8 2.8L21.2 21.2M6.5 18H15.15L7.1 9.95Q7.05 10.23 7.03 10.5 7 10.73 7 11H6.5Q5.05 11 4.03 12.03 3 13.05 3 14.5 3 15.95 4.03 17 5.05 18 6.5 18M11.13 14M21.6 18.75L20.15 17.35Q20.58 17 20.79 16.54 21 16.08 21 15.5 21 14.45 20.27 13.73 19.55 13 18.5 13H17V11Q17 8.93 15.54 7.46 14.08 6 12 6 11.33 6 10.7 6.16 10.07 6.33 9.5 6.68L8.05 5.23Q8.93 4.63 9.91 4.31 10.9 4 12 4 14.93 4 16.96 6.04 19 8.07 19 11 20.73 11.2 21.86 12.5 23 13.78 23 15.5 23 16.5 22.63 17.31 22.25 18.15 21.6 18.75M14.83 12.03Z" /></svg>',
|
||||||
codeTags: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14.6,16.6L19.2,12L14.6,7.4L16,6L22,12L16,18L14.6,16.6M9.4,16.6L4.8,12L9.4,7.4L8,6L2,12L8,18L9.4,16.6Z" /></svg>',
|
codeTags: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14.6,16.6L19.2,12L14.6,7.4L16,6L22,12L16,18L14.6,16.6M9.4,16.6L4.8,12L9.4,7.4L8,6L2,12L8,18L9.4,16.6Z" /></svg>',
|
||||||
cog: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z" /></svg>',
|
cog: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z" /></svg>',
|
||||||
compassOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7,17L10.2,10.2L17,7L13.8,13.8L7,17M12,11.1A0.9,0.9 0 0,0 11.1,12A0.9,0.9 0 0,0 12,12.9A0.9,0.9 0 0,0 12.9,12A0.9,0.9 0 0,0 12,11.1M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" /></svg>',
|
compassOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7,17L10.2,10.2L17,7L13.8,13.8L7,17M12,11.1A0.9,0.9 0 0,0 11.1,12A0.9,0.9 0 0,0 12,12.9A0.9,0.9 0 0,0 12.9,12A0.9,0.9 0 0,0 12,11.1M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" /></svg>',
|
||||||
dotsHorizontal: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M16,12A2,2 0 0,1 18,10A2,2 0 0,1 20,12A2,2 0 0,1 18,14A2,2 0 0,1 16,12M10,12A2,2 0 0,1 12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12M4,12A2,2 0 0,1 6,10A2,2 0 0,1 8,12A2,2 0 0,1 6,14A2,2 0 0,1 4,12Z" /></svg>',
|
dotsHorizontal: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M16,12A2,2 0 0,1 18,10A2,2 0 0,1 20,12A2,2 0 0,1 18,14A2,2 0 0,1 16,12M10,12A2,2 0 0,1 12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12M4,12A2,2 0 0,1 6,10A2,2 0 0,1 8,12A2,2 0 0,1 6,14A2,2 0 0,1 4,12Z" /></svg>',
|
||||||
downloadOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13,5V11H14.17L12,13.17L9.83,11H11V5H13M15,3H9V9H5L12,16L19,9H15V3M19,18H5V20H19V18Z" /></svg>',
|
downloadOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13,5V11H14.17L12,13.17L9.83,11H11V5H13M15,3H9V9H5L12,16L19,9H15V3M19,18H5V20H19V18Z" /></svg>',
|
||||||
glasses: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3,10C2.76,10 2.55,10.09 2.41,10.25C2.27,10.4 2.21,10.62 2.24,10.86L2.74,13.85C2.82,14.5 3.4,15 4,15H7C7.64,15 8.36,14.44 8.5,13.82L9.56,10.63C9.6,10.5 9.57,10.31 9.5,10.19C9.39,10.07 9.22,10 9,10H3M7,17H4C2.38,17 0.96,15.74 0.76,14.14L0.26,11.15C0.15,10.3 0.39,9.5 0.91,8.92C1.43,8.34 2.19,8 3,8H9C9.83,8 10.58,8.35 11.06,8.96C11.17,9.11 11.27,9.27 11.35,9.45C11.78,9.36 12.22,9.36 12.64,9.45C12.72,9.27 12.82,9.11 12.94,8.96C13.41,8.35 14.16,8 15,8H21C21.81,8 22.57,8.34 23.09,8.92C23.6,9.5 23.84,10.3 23.74,11.11L23.23,14.18C23.04,15.74 21.61,17 20,17H17C15.44,17 13.92,15.81 13.54,14.3L12.64,11.59C12.26,11.31 11.73,11.31 11.35,11.59L10.43,14.37C10.07,15.82 8.56,17 7,17M15,10C14.78,10 14.61,10.07 14.5,10.19C14.42,10.31 14.4,10.5 14.45,10.7L15.46,13.75C15.64,14.44 16.36,15 17,15H20C20.59,15 21.18,14.5 21.25,13.89L21.76,10.82C21.79,10.62 21.73,10.4 21.59,10.25C21.45,10.09 21.24,10 21,10H15Z" /></svg>',
|
glasses: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3,10C2.76,10 2.55,10.09 2.41,10.25C2.27,10.4 2.21,10.62 2.24,10.86L2.74,13.85C2.82,14.5 3.4,15 4,15H7C7.64,15 8.36,14.44 8.5,13.82L9.56,10.63C9.6,10.5 9.57,10.31 9.5,10.19C9.39,10.07 9.22,10 9,10H3M7,17H4C2.38,17 0.96,15.74 0.76,14.14L0.26,11.15C0.15,10.3 0.39,9.5 0.91,8.92C1.43,8.34 2.19,8 3,8H9C9.83,8 10.58,8.35 11.06,8.96C11.17,9.11 11.27,9.27 11.35,9.45C11.78,9.36 12.22,9.36 12.64,9.45C12.72,9.27 12.82,9.11 12.94,8.96C13.41,8.35 14.16,8 15,8H21C21.81,8 22.57,8.34 23.09,8.92C23.6,9.5 23.84,10.3 23.74,11.11L23.23,14.18C23.04,15.74 21.61,17 20,17H17C15.44,17 13.92,15.81 13.54,14.3L12.64,11.59C12.26,11.31 11.73,11.31 11.35,11.59L10.43,14.37C10.07,15.82 8.56,17 7,17M15,10C14.78,10 14.61,10.07 14.5,10.19C14.42,10.31 14.4,10.5 14.45,10.7L15.46,13.75C15.64,14.44 16.36,15 17,15H20C20.59,15 21.18,14.5 21.25,13.89L21.76,10.82C21.79,10.62 21.73,10.4 21.59,10.25C21.45,10.09 21.24,10 21,10H15Z" /></svg>',
|
||||||
helpCircleOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11,18H13V16H11V18M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,6A4,4 0 0,0 8,10H10A2,2 0 0,1 12,8A2,2 0 0,1 14,10C14,12 11,11.75 11,15H13C13,12.75 16,12.5 16,10A4,4 0 0,0 12,6Z" /></svg>',
|
helpCircleOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11,18H13V16H11V18M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,6A4,4 0 0,0 8,10H10A2,2 0 0,1 12,8A2,2 0 0,1 14,10C14,12 11,11.75 11,15H13C13,12.75 16,12.5 16,10A4,4 0 0,0 12,6Z" /></svg>',
|
||||||
history: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13.5,8H12V13L16.28,15.54L17,14.33L13.5,12.25V8M13,3A9,9 0 0,0 4,12H1L4.96,16.03L9,12H6A7,7 0 0,1 13,5A7,7 0 0,1 20,12A7,7 0 0,1 13,19C11.07,19 9.32,18.21 8.06,16.94L6.64,18.36C8.27,20 10.5,21 13,21A9,9 0 0,0 22,12A9,9 0 0,0 13,3" /></svg>',
|
history: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13.5,8H12V13L16.28,15.54L17,14.33L13.5,12.25V8M13,3A9,9 0 0,0 4,12H1L4.96,16.03L9,12H6A7,7 0 0,1 13,5A7,7 0 0,1 20,12A7,7 0 0,1 13,19C11.07,19 9.32,18.21 8.06,16.94L6.64,18.36C8.27,20 10.5,21 13,21A9,9 0 0,0 22,12A9,9 0 0,0 13,3" /></svg>',
|
||||||
informationOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z" /></svg>',
|
informationOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z" /></svg>',
|
||||||
labelOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M16,17H5V7H16L19.55,12M17.63,5.84C17.27,5.33 16.67,5 16,5H5A2,2 0 0,0 3,7V17A2,2 0 0,0 5,19H16C16.67,19 17.27,18.66 17.63,18.15L22,12L17.63,5.84Z" /></svg>',
|
labelOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M16,17H5V7H16L19.55,12M17.63,5.84C17.27,5.33 16.67,5 16,5H5A2,2 0 0,0 3,7V17A2,2 0 0,0 5,19H16C16.67,19 17.27,18.66 17.63,18.15L22,12L17.63,5.84Z" /></svg>',
|
||||||
paletteOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2C17.5,2 22,6 22,11A6,6 0 0,1 16,17H14.2C13.9,17 13.7,17.2 13.7,17.5C13.7,17.6 13.8,17.7 13.8,17.8C14.2,18.3 14.4,18.9 14.4,19.5C14.5,20.9 13.4,22 12,22M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C12.3,20 12.5,19.8 12.5,19.5C12.5,19.3 12.4,19.2 12.4,19.1C12,18.6 11.8,18.1 11.8,17.5C11.8,16.1 12.9,15 14.3,15H16A4,4 0 0,0 20,11C20,7.1 16.4,4 12,4M6.5,10C7.3,10 8,10.7 8,11.5C8,12.3 7.3,13 6.5,13C5.7,13 5,12.3 5,11.5C5,10.7 5.7,10 6.5,10M9.5,6C10.3,6 11,6.7 11,7.5C11,8.3 10.3,9 9.5,9C8.7,9 8,8.3 8,7.5C8,6.7 8.7,6 9.5,6M14.5,6C15.3,6 16,6.7 16,7.5C16,8.3 15.3,9 14.5,9C13.7,9 13,8.3 13,7.5C13,6.7 13.7,6 14.5,6M17.5,10C18.3,10 19,10.7 19,11.5C19,12.3 18.3,13 17.5,13C16.7,13 16,12.3 16,11.5C16,10.7 16.7,10 17.5,10Z" /></svg>',
|
paletteOutline: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2C17.5,2 22,6 22,11A6,6 0 0,1 16,17H14.2C13.9,17 13.7,17.2 13.7,17.5C13.7,17.6 13.8,17.7 13.8,17.8C14.2,18.3 14.4,18.9 14.4,19.5C14.5,20.9 13.4,22 12,22M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C12.3,20 12.5,19.8 12.5,19.5C12.5,19.3 12.4,19.2 12.4,19.1C12,18.6 11.8,18.1 11.8,17.5C11.8,16.1 12.9,15 14.3,15H16A4,4 0 0,0 20,11C20,7.1 16.4,4 12,4M6.5,10C7.3,10 8,10.7 8,11.5C8,12.3 7.3,13 6.5,13C5.7,13 5,12.3 5,11.5C5,10.7 5.7,10 6.5,10M9.5,6C10.3,6 11,6.7 11,7.5C11,8.3 10.3,9 9.5,9C8.7,9 8,8.3 8,7.5C8,6.7 8.7,6 9.5,6M14.5,6C15.3,6 16,6.7 16,7.5C16,8.3 15.3,9 14.5,9C13.7,9 13,8.3 13,7.5C13,6.7 13.7,6 14.5,6M17.5,10C18.3,10 19,10.7 19,11.5C19,12.3 18.3,13 17.5,13C16.7,13 16,12.3 16,11.5C16,10.7 16.7,10 17.5,10Z" /></svg>',
|
||||||
queryStats: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="m105-233-65-47 200-320 120 140 160-260 109 163q-23 1-43.5 5.5T545-539l-22-33-152 247-121-141-145 233ZM863-40 738-165q-20 14-44.5 21t-50.5 7q-75 0-127.5-52.5T463-317q0-75 52.5-127.5T643-497q75 0 127.5 52.5T823-317q0 26-7 50.5T795-221L920-97l-57 57ZM643-217q42 0 71-29t29-71q0-42-29-71t-71-29q-42 0-71 29t-29 71q0 42 29 71t71 29Zm89-320q-19-8-39.5-13t-42.5-6l205-324 65 47-188 296Z"/></svg>',
|
queryStats: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="m105-233-65-47 200-320 120 140 160-260 109 163q-23 1-43.5 5.5T545-539l-22-33-152 247-121-141-145 233ZM863-40 738-165q-20 14-44.5 21t-50.5 7q-75 0-127.5-52.5T463-317q0-75 52.5-127.5T643-497q75 0 127.5 52.5T823-317q0 26-7 50.5T795-221L920-97l-57 57ZM643-217q42 0 71-29t29-71q0-42-29-71t-71-29q-42 0-71 29t-29 71q0 42 29 71t71 29Zm89-320q-19-8-39.5-13t-42.5-6l205-324 65 47-188 296Z"/></svg>',
|
||||||
security: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,12H19C18.47,16.11 15.72,19.78 12,20.92V12H5V6.3L12,3.19M12,1L3,5V11C3,16.55 6.84,21.73 12,23C17.16,21.73 21,16.55 21,11V5L12,1Z" /></svg>',
|
security: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,12H19C18.47,16.11 15.72,19.78 12,20.92V12H5V6.3L12,3.19M12,1L3,5V11C3,16.55 6.84,21.73 12,23C17.16,21.73 21,16.55 21,11V5L12,1Z" /></svg>',
|
||||||
sync: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,18A6,6 0 0,1 6,12C6,11 6.25,10.03 6.7,9.2L5.24,7.74C4.46,8.97 4,10.43 4,12A8,8 0 0,0 12,20V23L16,19L12,15M12,4V1L8,5L12,9V6A6,6 0 0,1 18,12C18,13 17.75,13.97 17.3,14.8L18.76,16.26C19.54,15.03 20,13.57 20,12A8,8 0 0,0 12,4Z" /></svg>',
|
sync: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,18A6,6 0 0,1 6,12C6,11 6.25,10.03 6.7,9.2L5.24,7.74C4.46,8.97 4,10.43 4,12A8,8 0 0,0 12,20V23L16,19L12,15M12,4V1L8,5L12,9V6A6,6 0 0,1 18,12C18,13 17.75,13.97 17.3,14.8L18.76,16.26C19.54,15.03 20,13.57 20,12A8,8 0 0,0 12,4Z" /></svg>',
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Navigation {
|
interface Navigation {
|
||||||
name: string
|
name: string
|
||||||
icon?: string
|
icon?: string
|
||||||
dependsOn?: string
|
dependsOn?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigationMappings: Record<string, Navigation> = {
|
const navigationMappings: Record<string, Navigation> = {
|
||||||
// Main menus
|
// Main menus
|
||||||
"main_library": { name: "Library", icon: iconMappings.bookmarkBoxOutline },
|
'main_library': { name: 'Library', icon: iconMappings.bookmarkBoxOutline },
|
||||||
"main_updates": { name: "Updates", icon: iconMappings.alertDecagramOutline },
|
'main_updates': { name: 'Updates', icon: iconMappings.alertDecagramOutline },
|
||||||
"main_history": { name: "History", icon: iconMappings.history },
|
'main_history': { name: 'History', icon: iconMappings.history },
|
||||||
"main_browse": { name: "Browse", icon: iconMappings.compassOutline },
|
'main_browse': { name: 'Browse', icon: iconMappings.compassOutline },
|
||||||
"main_more": { name: "More", icon: iconMappings.dotsHorizontal },
|
'main_more': { name: 'More', icon: iconMappings.dotsHorizontal },
|
||||||
|
|
||||||
// Browse menu
|
// Browse menu
|
||||||
"sources": { name: "Sources", dependsOn: "main_browse" },
|
'sources': { name: 'Sources', dependsOn: 'main_browse' },
|
||||||
"extensions": { name: "Extensions", dependsOn: "main_browse" },
|
'extensions': { name: 'Extensions', dependsOn: 'main_browse' },
|
||||||
"migrate": { name: "Migrate", dependsOn: "main_browse" },
|
'migrate': { name: 'Migrate', dependsOn: 'main_browse' },
|
||||||
|
|
||||||
// More menu
|
// More menu
|
||||||
"downloaded-only": { name: "Downloaded only", icon: iconMappings.cloudOffOutline, dependsOn: "main_more" },
|
'downloaded-only': { name: 'Downloaded only', icon: iconMappings.cloudOffOutline, dependsOn: 'main_more' },
|
||||||
"incognito-mode": { name: "Incognito mode", icon: iconMappings.glasses, dependsOn: "main_more" },
|
'incognito-mode': { name: 'Incognito mode', icon: iconMappings.glasses, dependsOn: 'main_more' },
|
||||||
"download-queue": { name: "Download queue", icon: iconMappings.downloadOutline, dependsOn: "main_more" },
|
'download-queue': { name: 'Download queue', icon: iconMappings.downloadOutline, dependsOn: 'main_more' },
|
||||||
"categories": { name: "Categories", icon: iconMappings.labelOutline, dependsOn: "main_more" },
|
'categories': { name: 'Categories', icon: iconMappings.labelOutline, dependsOn: 'main_more' },
|
||||||
"statistics": { name: "Statistics", icon: iconMappings.queryStats, dependsOn: "main_more" },
|
'statistics': { name: 'Statistics', icon: iconMappings.queryStats, dependsOn: 'main_more' },
|
||||||
"backup-and-restore": { name: "Backup and restore", icon: iconMappings.backupRestore, dependsOn: "main_more" },
|
'backup-and-restore': { name: 'Backup and restore', icon: iconMappings.backupRestore, dependsOn: 'main_more' },
|
||||||
"settings": { name: "Settings", icon: iconMappings.cog, dependsOn: "main_more" },
|
'settings': { name: 'Settings', icon: iconMappings.cog, dependsOn: 'main_more' },
|
||||||
"about": { name: "About", icon: iconMappings.informationOutline, dependsOn: "main_more" },
|
'about': { name: 'About', icon: iconMappings.informationOutline, dependsOn: 'main_more' },
|
||||||
"help": { name: "Help", icon: iconMappings.helpCircleOutline, dependsOn: "main_more" },
|
'help': { name: 'Help', icon: iconMappings.helpCircleOutline, dependsOn: 'main_more' },
|
||||||
|
|
||||||
// Settings submenu
|
// Settings submenu
|
||||||
"appearance": { name: "Appearance", icon: iconMappings.paletteOutline, dependsOn: "settings" },
|
'appearance': { name: 'Appearance', icon: iconMappings.paletteOutline, dependsOn: 'settings' },
|
||||||
"library": { name: "Library", icon: iconMappings.bookmarkBoxOutline, dependsOn: "settings" },
|
'library': { name: 'Library', icon: iconMappings.bookmarkBoxOutline, dependsOn: 'settings' },
|
||||||
"downloads": { name: "Downloads", icon: iconMappings.downloadOutline, dependsOn: "settings" },
|
'downloads': { name: 'Downloads', icon: iconMappings.downloadOutline, dependsOn: 'settings' },
|
||||||
"tracking": { name: "Tracking", icon: iconMappings.sync, dependsOn: "settings" },
|
'tracking': { name: 'Tracking', icon: iconMappings.sync, dependsOn: 'settings' },
|
||||||
"browse": { name: "Browse", icon: iconMappings.compassOutline, dependsOn: "settings" },
|
'browse': { name: 'Browse', icon: iconMappings.compassOutline, dependsOn: 'settings' },
|
||||||
"security-and-privacy": { name: "Security and privacy", icon: iconMappings.security, dependsOn: "settings" },
|
'security-and-privacy': { name: 'Security and privacy', icon: iconMappings.security, dependsOn: 'settings' },
|
||||||
"reader": { name: "Reader", icon: iconMappings.bookOpenOutline, dependsOn: "settings" },
|
'reader': { name: 'Reader', icon: iconMappings.bookOpenOutline, dependsOn: 'settings' },
|
||||||
"advanced": { name: "Advanced", icon: iconMappings.codeTags, dependsOn: "settings" },
|
'advanced': { name: 'Advanced', icon: iconMappings.codeTags, dependsOn: 'settings' },
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateNavigationHtml(navKey: string) {
|
function generateNavigationHtml(navKey: string) {
|
||||||
const navData = navigationMappings[navKey]
|
const navData = navigationMappings[navKey]
|
||||||
|
|
||||||
if (!navData) {
|
if (!navData)
|
||||||
return "<strong style='color:var(--vp-c-danger-1)'>Unsupported Navigation!</strong>"
|
return '<strong style=\'color:var(--vp-c-danger-1)\'>Unsupported Navigation!</strong>'
|
||||||
}
|
|
||||||
|
|
||||||
const { name, icon, dependsOn } = navData
|
const { name, icon, dependsOn } = navData
|
||||||
|
|
||||||
const iconHtml = icon ?? ""
|
const iconHtml = icon ?? ''
|
||||||
let html = `<span class='shortcode navigation ${navKey}'>${iconHtml}<span class="name">${name}</span></span>`
|
let html = `<span class='shortcode navigation ${navKey}'>${iconHtml}<span class="name">${name}</span></span>`
|
||||||
|
|
||||||
if (dependsOn) {
|
if (dependsOn)
|
||||||
html = `${generateNavigationHtml(dependsOn)} -> ${html}`
|
html = `${generateNavigationHtml(dependsOn)} -> ${html}`
|
||||||
}
|
|
||||||
|
|
||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
|
||||||
const shortcodes = {
|
const shortcodes = {
|
||||||
nav: {
|
nav: {
|
||||||
render({ to }) {
|
render({ to }) {
|
||||||
return generateNavigationHtml(to)
|
return generateNavigationHtml(to)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default shortcodes
|
export default shortcodes
|
||||||
|
@ -1,78 +1,78 @@
|
|||||||
import type { DefaultTheme } from "vitepress"
|
import type { DefaultTheme } from 'vitepress'
|
||||||
|
|
||||||
import nav from "./navigation/navbar"
|
import nav from './navigation/navbar'
|
||||||
import sidebar from "./navigation/sidebar"
|
import sidebar from './navigation/sidebar'
|
||||||
|
|
||||||
const themeConfig: DefaultTheme.Config = {
|
const themeConfig: DefaultTheme.Config = {
|
||||||
logo: {
|
logo: {
|
||||||
src: "/img/logo-128px.png",
|
src: '/img/logo-128px.png',
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
|
|
||||||
nav,
|
nav,
|
||||||
sidebar,
|
sidebar,
|
||||||
|
|
||||||
outline: [2, 3],
|
outline: [2, 3],
|
||||||
|
|
||||||
socialLinks: [
|
socialLinks: [
|
||||||
{
|
{
|
||||||
icon: "github",
|
icon: 'github',
|
||||||
link: "https://github.com/tachiyomiorg/tachiyomi",
|
link: 'https://github.com/tachiyomiorg/tachiyomi',
|
||||||
ariaLabel: "Project GitHub",
|
ariaLabel: 'Project GitHub',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "discord",
|
icon: 'discord',
|
||||||
link: "https://discord.gg/tachiyomi",
|
link: 'https://discord.gg/tachiyomi',
|
||||||
ariaLabel: "Discord Server",
|
ariaLabel: 'Discord Server',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "x",
|
icon: 'x',
|
||||||
link: "https://twitter.com/tachiyomiorg",
|
link: 'https://twitter.com/tachiyomiorg',
|
||||||
ariaLabel: "X Page",
|
ariaLabel: 'X Page',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "facebook",
|
icon: 'facebook',
|
||||||
link: "https://facebook.com/tachiyomiorg",
|
link: 'https://facebook.com/tachiyomiorg',
|
||||||
ariaLabel: "Facebook Page",
|
ariaLabel: 'Facebook Page',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: {
|
icon: {
|
||||||
svg: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.687-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.913 2.961.913.477 0 2.105-.056 2.961-.913a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z"/></svg>',
|
svg: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.687-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.913 2.961.913.477 0 2.105-.056 2.961-.913a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z"/></svg>',
|
||||||
},
|
},
|
||||||
link: "https://reddit.com/r/Tachiyomi",
|
link: 'https://reddit.com/r/Tachiyomi',
|
||||||
ariaLabel: "Support subreddit",
|
ariaLabel: 'Support subreddit',
|
||||||
},
|
},
|
||||||
// { icon: "instagram", link: "https://instagram.com/tachiyomiorg", ariaLabel: "Instagram Page" },
|
// { icon: "instagram", link: "https://instagram.com/tachiyomiorg", ariaLabel: "Instagram Page" },
|
||||||
],
|
],
|
||||||
|
|
||||||
footer: {
|
footer: {
|
||||||
message: "<a href=\"https://www.apache.org/licenses/LICENSE-2.0\" target=\"_blank\">Open-source Apache Licensed</a> <span class=\"divider\">|</span> <a href=\"/privacy/\">Privacy policy</a> <span class=\"divider\">|</span> Powered by <a target=\"_blank\" href=\"https://www.netlify.com/\">Netlify <img src=\"/img/logo-netlify.svg\" alt=\"Netlify Logo\" height=\"12px\" width=\"12px\" style=\"display: inline-block\"></a>",
|
message: '<a href="https://www.apache.org/licenses/LICENSE-2.0" target="_blank">Open-source Apache Licensed</a> <span class="divider">|</span> <a href="/privacy/">Privacy policy</a> <span class="divider">|</span> Powered by <a target="_blank" href="https://www.netlify.com/">Netlify <img src="/img/logo-netlify.svg" alt="Netlify Logo" height="12px" width="12px" style="display: inline-block"></a>',
|
||||||
copyright: `Copyright © 2015 - ${new Date().getFullYear()} Javier Tomás`,
|
copyright: `Copyright © 2015 - ${new Date().getFullYear()} Javier Tomás`,
|
||||||
},
|
},
|
||||||
|
|
||||||
editLink: {
|
editLink: {
|
||||||
pattern: "https://github.com/tachiyomiorg/website/edit/main/website/src/:path",
|
pattern: 'https://github.com/tachiyomiorg/website/edit/main/website/src/:path',
|
||||||
text: "Help us improve this page",
|
text: 'Help us improve this page',
|
||||||
},
|
},
|
||||||
|
|
||||||
lastUpdated: {
|
lastUpdated: {
|
||||||
text: "Last updated",
|
text: 'Last updated',
|
||||||
formatOptions: {
|
formatOptions: {
|
||||||
forceLocale: true,
|
forceLocale: true,
|
||||||
dateStyle: "long",
|
dateStyle: 'long',
|
||||||
timeStyle: "short",
|
timeStyle: 'short',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
search: {
|
search: {
|
||||||
provider: "algolia",
|
provider: 'algolia',
|
||||||
options: {
|
options: {
|
||||||
appId: "2C8EHFTRW7",
|
appId: '2C8EHFTRW7',
|
||||||
apiKey: "ee38c6e04295e4d206399ab59a58ea9a",
|
apiKey: 'ee38c6e04295e4d206399ab59a58ea9a',
|
||||||
indexName: "tachiyomi",
|
indexName: 'tachiyomi',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default themeConfig
|
export default themeConfig
|
||||||
|
@ -1,64 +1,64 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useData } from "vitepress"
|
import { useData } from 'vitepress'
|
||||||
import DefaultTheme from "vitepress/theme"
|
import DefaultTheme from 'vitepress/theme'
|
||||||
import { nextTick, provide } from "vue"
|
import { nextTick, provide } from 'vue'
|
||||||
|
|
||||||
const { isDark } = useData()
|
const { isDark } = useData()
|
||||||
|
|
||||||
function shouldEnableTransitions() {
|
function shouldEnableTransitions() {
|
||||||
return "startViewTransition" in document
|
return 'startViewTransition' in document
|
||||||
&& window.matchMedia("(prefers-reduced-motion: no-preference)").matches
|
&& window.matchMedia('(prefers-reduced-motion: no-preference)').matches
|
||||||
}
|
}
|
||||||
|
|
||||||
provide("toggle-appearance", async ({ clientX: x, clientY: y }: MouseEvent) => {
|
provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
|
||||||
if (!shouldEnableTransitions()) {
|
if (!shouldEnableTransitions()) {
|
||||||
isDark.value = !isDark.value
|
isDark.value = !isDark.value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const clipPath = [
|
const clipPath = [
|
||||||
`circle(0px at ${x}px ${y}px)`,
|
`circle(0px at ${x}px ${y}px)`,
|
||||||
`circle(${Math.hypot(
|
`circle(${Math.hypot(
|
||||||
Math.max(x, innerWidth - x),
|
Math.max(x, innerWidth - x),
|
||||||
Math.max(y, innerHeight - y),
|
Math.max(y, innerHeight - y),
|
||||||
)}px at ${x}px ${y}px)`,
|
)}px at ${x}px ${y}px)`,
|
||||||
]
|
]
|
||||||
|
|
||||||
// @ts-expect-error Missing types as its experimental
|
// @ts-expect-error Missing types as its experimental
|
||||||
await document.startViewTransition(async () => {
|
await document.startViewTransition(async () => {
|
||||||
isDark.value = !isDark.value
|
isDark.value = !isDark.value
|
||||||
await nextTick()
|
await nextTick()
|
||||||
}).ready
|
}).ready
|
||||||
|
|
||||||
document.documentElement.animate(
|
document.documentElement.animate(
|
||||||
{ clipPath: isDark.value ? clipPath.reverse() : clipPath },
|
{ clipPath: isDark.value ? clipPath.reverse() : clipPath },
|
||||||
{
|
{
|
||||||
duration: 300,
|
duration: 300,
|
||||||
easing: "ease-in",
|
easing: 'ease-in',
|
||||||
pseudoElement: `::view-transition-${isDark.value ? "old" : "new"}(root)`,
|
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DefaultTheme.Layout />
|
<DefaultTheme.Layout />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
::view-transition-old(root),
|
::view-transition-old(root),
|
||||||
::view-transition-new(root) {
|
::view-transition-new(root) {
|
||||||
animation: none
|
animation: none
|
||||||
mix-blend-mode: normal
|
mix-blend-mode: normal
|
||||||
}
|
}
|
||||||
|
|
||||||
::view-transition-old(root),
|
::view-transition-old(root),
|
||||||
.dark::view-transition-new(root) {
|
.dark::view-transition-new(root) {
|
||||||
z-index: 1
|
z-index: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
::view-transition-new(root),
|
::view-transition-new(root),
|
||||||
.dark::view-transition-old(root) {
|
.dark::view-transition-old(root) {
|
||||||
z-index: 9999
|
z-index: 9999
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, toRefs } from "vue"
|
import { computed, toRefs } from 'vue'
|
||||||
import MarkdownIt from "markdown-it"
|
import MarkdownIt from 'markdown-it'
|
||||||
import { type AppRelease, data as release } from "../data/release.data"
|
import { type AppRelease, data as release } from '../data/release.data'
|
||||||
import Contributors from "./Contributors.vue"
|
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)
|
||||||
@ -10,107 +10,107 @@ const { type } = toRefs(props)
|
|||||||
const md = new MarkdownIt()
|
const md = new MarkdownIt()
|
||||||
|
|
||||||
const changelog = computed(() => {
|
const changelog = 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/")
|
.replace('https://github.com/tachiyomiorg/tachiyomi/releases', '/changelogs/')
|
||||||
|
|
||||||
return md.render(flavoredString)
|
return md.render(flavoredString)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="changelog">
|
<div class="changelog">
|
||||||
<header>
|
<header>
|
||||||
<IconNewspaperVariant />
|
<IconNewspaperVariant />
|
||||||
<h2>Changelog</h2>
|
<h2>Changelog</h2>
|
||||||
</header>
|
</header>
|
||||||
<div v-html="changelog" />
|
<div v-html="changelog" />
|
||||||
<Contributors
|
<Contributors
|
||||||
:body="release[type].body!"
|
:body="release[type].body!"
|
||||||
:author="release[type].author.login"
|
:author="release[type].author.login"
|
||||||
:tag="release[type].tag_name"
|
:tag="release[type].tag_name"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="fullChangelog">
|
<div class="fullChangelog">
|
||||||
<p>
|
<p>
|
||||||
View the full release
|
View the full release
|
||||||
<a href="https://github.com/tachiyomiorg/tachiyomi/releases/latest" target="_blank" rel="noopener">
|
<a href="https://github.com/tachiyomiorg/tachiyomi/releases/latest" target="_blank" rel="noopener">
|
||||||
here
|
here
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.changelog {
|
.changelog {
|
||||||
display: block
|
display: block
|
||||||
border: 1px solid var(--vp-c-bg-soft)
|
border: 1px solid var(--vp-c-bg-soft)
|
||||||
border-radius: 12px
|
border-radius: 12px
|
||||||
background-color: var(--vp-c-bg-soft)
|
background-color: var(--vp-c-bg-soft)
|
||||||
transition: border-color 0.25s, background-color 0.25s
|
transition: border-color 0.25s, background-color 0.25s
|
||||||
padding: 24px
|
padding: 24px
|
||||||
height: 100%
|
height: 100%
|
||||||
margin: 1.5em auto 0.5em
|
margin: 1.5em auto 0.5em
|
||||||
|
|
||||||
header {
|
header {
|
||||||
display: flex
|
display: flex
|
||||||
justify-content: center
|
justify-content: center
|
||||||
align-items: baseline
|
align-items: baseline
|
||||||
margin: 0 0 1rem
|
margin: 0 0 1rem
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
font-size: 1.2em
|
font-size: 1.2em
|
||||||
margin-right: 0.5rem
|
margin-right: 0.5rem
|
||||||
vertical-align: middle
|
vertical-align: middle
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 1.5rem
|
font-size: 1.5rem
|
||||||
margin: 0
|
margin: 0
|
||||||
padding: 0
|
padding: 0
|
||||||
color: var(--vp-c-text-1)
|
color: var(--vp-c-text-1)
|
||||||
border: none
|
border: none
|
||||||
}
|
}
|
||||||
|
|
||||||
div > p {
|
div > p {
|
||||||
margin: 0 0 1rem
|
margin: 0 0 1rem
|
||||||
color: var(--vp-c-text-2)
|
color: var(--vp-c-text-2)
|
||||||
font-size: 0.9rem
|
font-size: 0.9rem
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border-radius: 8px
|
border-radius: 8px
|
||||||
border-collapse: collapse
|
border-collapse: collapse
|
||||||
border: 1px solid var(--vp-c-divider)
|
border: 1px solid var(--vp-c-divider)
|
||||||
|
|
||||||
tr,
|
tr,
|
||||||
th,
|
th,
|
||||||
td {
|
td {
|
||||||
border: none
|
border: none
|
||||||
width: 100%
|
width: 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
tbody tr {
|
tbody tr {
|
||||||
border-top: 1px solid var(--vp-c-divider)
|
border-top: 1px solid var(--vp-c-divider)
|
||||||
}
|
}
|
||||||
|
|
||||||
tr > td {
|
tr > td {
|
||||||
&:first-child {
|
&:first-child {
|
||||||
color: var(--vp-c-text-2)
|
color: var(--vp-c-text-2)
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
font-family: var(--vp-font-family-mono)
|
font-family: var(--vp-font-family-mono)
|
||||||
font-size: var(--vp-code-font-size)
|
font-size: var(--vp-code-font-size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fullChangelog {
|
.fullChangelog {
|
||||||
margin: 0 0 1rem
|
margin: 0 0 1rem
|
||||||
color: var(--vp-c-text-2)
|
color: var(--vp-c-text-2)
|
||||||
font-size: 0.9rem
|
font-size: 0.9rem
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,69 +1,69 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import MarkdownIt from "markdown-it"
|
import MarkdownIt from 'markdown-it'
|
||||||
import { data as changelogs } from "../data/changelogs.data"
|
import { data as changelogs } from '../data/changelogs.data'
|
||||||
import Contributors from "./Contributors.vue"
|
import Contributors from './Contributors.vue'
|
||||||
|
|
||||||
const md = new MarkdownIt()
|
const md = new MarkdownIt()
|
||||||
|
|
||||||
function renderMarkdown(string: string | null | undefined) {
|
function renderMarkdown(string: string | null | undefined) {
|
||||||
const body = string ?? "No changelog provided."
|
const body = string ?? 'No changelog provided.'
|
||||||
const flavoredString = body
|
const flavoredString = body
|
||||||
.split(/---\r\n\r\n### Checksums|---\r\n\r\nMD5/)[0]
|
.split(/---\r\n\r\n### Checksums|---\r\n\r\nMD5/)[0]
|
||||||
.replace(/(?<=\(|(, ))@(.*?)(?=\)|(, ))/g, "[@$2](https://github.com/$2)")
|
.replace(/(?<=\(|(, ))@(.*?)(?=\)|(, ))/g, '[@$2](https://github.com/$2)')
|
||||||
.replace(/#(\d+)/g, "[#$1](https://github.com/tachiyomiorg/tachiyomi/issues/$1)")
|
.replace(/#(\d+)/g, '[#$1](https://github.com/tachiyomiorg/tachiyomi/issues/$1)')
|
||||||
.replace(/^Check out the .*past release notes.* if you're.*$/m, "")
|
.replace(/^Check out the .*past release notes.* if you're.*$/m, '')
|
||||||
.replace(/https\:\/\/github.com\/tachiyomiorg\/tachiyomi\/releases\/tag\/(.*?)/g, "#$1")
|
.replace(/https\:\/\/github.com\/tachiyomiorg\/tachiyomi\/releases\/tag\/(.*?)/g, '#$1')
|
||||||
.trim()
|
.trim()
|
||||||
|
|
||||||
return md.render(flavoredString)
|
return md.render(flavoredString)
|
||||||
}
|
}
|
||||||
|
|
||||||
const dateFormatter = new Intl.DateTimeFormat("en", {
|
const dateFormatter = new Intl.DateTimeFormat('en', {
|
||||||
dateStyle: "medium",
|
dateStyle: 'medium',
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-for="(release, index) of changelogs"
|
v-for="(release, index) of changelogs"
|
||||||
:key="release.tag_name"
|
:key="release.tag_name"
|
||||||
>
|
>
|
||||||
<h2 :id="index === 0 ? 'latest' : release.tag_name">
|
<h2 :id="index === 0 ? 'latest' : release.tag_name">
|
||||||
<a
|
<a
|
||||||
:href="release.html_url"
|
:href="release.html_url"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
{{ release.tag_name.substring(1) }}
|
{{ release.tag_name.substring(1) }}
|
||||||
</a>
|
</a>
|
||||||
<Badge v-if="index === 0" type="tip" text="Latest" />
|
<Badge v-if="index === 0" type="tip" text="Latest" />
|
||||||
<a
|
<a
|
||||||
class="header-anchor"
|
class="header-anchor"
|
||||||
:href="index === 0 ? '#latest' : `#${release.tag_name}`"
|
:href="index === 0 ? '#latest' : `#${release.tag_name}`"
|
||||||
:aria-label="`Permalink to "${release.tag_name}"`"
|
:aria-label="`Permalink to "${release.tag_name}"`"
|
||||||
/>
|
/>
|
||||||
</h2>
|
</h2>
|
||||||
<time :datetime="release.published_at!">
|
<time :datetime="release.published_at!">
|
||||||
{{ dateFormatter.format(new Date(release.published_at!)) }}
|
{{ dateFormatter.format(new Date(release.published_at!)) }}
|
||||||
</time>
|
</time>
|
||||||
<div v-html="renderMarkdown(release.body)" />
|
<div v-html="renderMarkdown(release.body)" />
|
||||||
<Contributors
|
<Contributors
|
||||||
:body="release.body!"
|
:body="release.body!"
|
||||||
:author="release.author.login"
|
:author="release.author.login"
|
||||||
:tag="release.tag_name"
|
:tag="release.tag_name"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
h2 {
|
h2 {
|
||||||
margin-bottom: 0
|
margin-bottom: 0
|
||||||
display: flex
|
display: flex
|
||||||
align-items: center
|
align-items: center
|
||||||
gap: 0.5rem
|
gap: 0.5rem
|
||||||
}
|
}
|
||||||
|
|
||||||
time {
|
time {
|
||||||
font-size: 0.875rem
|
font-size: 0.875rem
|
||||||
color: var(--vp-c-text-2)
|
color: var(--vp-c-text-2)
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,108 +1,106 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, toRefs } from "vue"
|
import { computed, ref, toRefs } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<{ body: string; author: string; tag: string }>()
|
const props = defineProps<{ body: string; author: string; tag: string }>()
|
||||||
const { body, author, tag } = toRefs(props)
|
const { body, author, tag } = toRefs(props)
|
||||||
|
|
||||||
function isHigherThan(tagName: string, reference: string) {
|
function isHigherThan(tagName: string, reference: string) {
|
||||||
return reference.localeCompare(tagName, undefined, { numeric: true, sensitivity: "base" }) >= 0
|
return reference.localeCompare(tagName, undefined, { numeric: true, sensitivity: 'base' }) >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const notMentioned = computed(() => {
|
const notMentioned = computed(() => {
|
||||||
return isHigherThan("v0.8.5", tag.value) ? ["arkon"] : []
|
return isHigherThan('v0.8.5', tag.value) ? ['arkon'] : []
|
||||||
})
|
})
|
||||||
|
|
||||||
const nonExistent = ref<string[]>([])
|
const nonExistent = ref<string[]>([])
|
||||||
|
|
||||||
const contributors = computed(() => {
|
const contributors = computed(() => {
|
||||||
const list = [...body.value.matchAll(/(?<=\(|(, ))@(.*?)(?=\)|(, ))/g)]
|
const list = [...body.value.matchAll(/(?<=\(|(, ))@(.*?)(?=\)|(, ))/g)]
|
||||||
.map((match) => match[2])
|
.map(match => match[2])
|
||||||
const uncredited = author.value.includes("[bot]")
|
const uncredited = author.value.includes('[bot]')
|
||||||
? notMentioned.value
|
? notMentioned.value
|
||||||
: [author.value, ...notMentioned.value]
|
: [author.value, ...notMentioned.value]
|
||||||
|
|
||||||
return [...new Set([...uncredited, ...list])].filter((user) => !nonExistent.value.includes(user))
|
return [...new Set([...uncredited, ...list])].filter(user => !nonExistent.value.includes(user))
|
||||||
})
|
})
|
||||||
|
|
||||||
const listFormatter = new Intl.ListFormat("en", {
|
const listFormatter = new Intl.ListFormat('en', {
|
||||||
style: "long",
|
style: 'long',
|
||||||
type: "conjunction",
|
type: 'conjunction',
|
||||||
})
|
})
|
||||||
|
|
||||||
const contributorsText = computed(() => {
|
const contributorsText = computed(() => {
|
||||||
if (contributors.value.length <= 3) {
|
if (contributors.value.length <= 3)
|
||||||
return listFormatter.format(contributors.value)
|
return listFormatter.format(contributors.value)
|
||||||
}
|
|
||||||
|
|
||||||
return listFormatter.format([
|
return listFormatter.format([
|
||||||
...contributors.value.slice(0, 2),
|
...contributors.value.slice(0, 2),
|
||||||
`${contributors.value.length - 2} other contributors`,
|
`${contributors.value.length - 2} other contributors`,
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
function addToNonExistent(user: string) {
|
function addToNonExistent(user: string) {
|
||||||
if (!nonExistent.value.includes(user)) {
|
if (!nonExistent.value.includes(user))
|
||||||
nonExistent.value.push(user)
|
nonExistent.value.push(user)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="contributors.length > 0" class="contributors">
|
<div v-if="contributors.length > 0" class="contributors">
|
||||||
<h3>Contributors</h3>
|
<h3>Contributors</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li
|
<li
|
||||||
v-for="contributor of contributors"
|
v-for="contributor of contributors"
|
||||||
:key="contributor"
|
:key="contributor"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
:href="`https://github.com/${contributor}`"
|
:href="`https://github.com/${contributor}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
:title="`${contributor} profile on GitHub`"
|
:title="`${contributor} profile on GitHub`"
|
||||||
:aria-label="`${contributor} profile on GitHub`"
|
:aria-label="`${contributor} profile on GitHub`"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`https://github.com/${contributor}.png?size=32`"
|
:src="`https://github.com/${contributor}.png?size=32`"
|
||||||
:alt="`@${contributor} profile picture`"
|
:alt="`@${contributor} profile picture`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="avatar"
|
class="avatar"
|
||||||
@error="addToNonExistent(contributor)"
|
@error="addToNonExistent(contributor)"
|
||||||
>
|
>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="names">
|
<div class="names">
|
||||||
{{ contributorsText }}
|
{{ contributorsText }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.contributors {
|
.contributors {
|
||||||
ul {
|
ul {
|
||||||
display: flex
|
display: flex
|
||||||
align-items: center
|
align-items: center
|
||||||
flex-wrap: wrap
|
flex-wrap: wrap
|
||||||
gap: 0.5rem
|
gap: 0.5rem
|
||||||
list-style-type: none
|
list-style-type: none
|
||||||
padding-left: 0
|
padding-left: 0
|
||||||
|
|
||||||
li + li {
|
li + li {
|
||||||
margin-top: 0
|
margin-top: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 32px
|
width: 32px
|
||||||
height: 32px
|
height: 32px
|
||||||
border-radius: 50%
|
border-radius: 50%
|
||||||
box-shadow: var(--vp-shadow-1)
|
box-shadow: var(--vp-shadow-1)
|
||||||
border: 1px solid var(--vp-c-divider)
|
border: 1px solid var(--vp-c-divider)
|
||||||
}
|
}
|
||||||
|
|
||||||
.names {
|
.names {
|
||||||
font-size: 0.875rem
|
font-size: 0.875rem
|
||||||
color: var(--vp-c-text-2)
|
color: var(--vp-c-text-2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref } from "vue"
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { useData } from "vitepress"
|
import { useData } from 'vitepress'
|
||||||
import type { DefaultTheme } from "vitepress/theme"
|
import type { DefaultTheme } from 'vitepress/theme'
|
||||||
|
|
||||||
import VPNavBarMenuLink from "vitepress/dist/client/theme-default/components/VPNavBarMenuLink.vue"
|
import VPNavBarMenuLink from 'vitepress/dist/client/theme-default/components/VPNavBarMenuLink.vue'
|
||||||
import VPNavBarMenuGroup from "vitepress/dist/client/theme-default/components/VPNavBarMenuGroup.vue"
|
import VPNavBarMenuGroup from 'vitepress/dist/client/theme-default/components/VPNavBarMenuGroup.vue'
|
||||||
|
|
||||||
import { data as release } from "../data/release.data"
|
import { data as release } from '../data/release.data'
|
||||||
|
|
||||||
const { theme } = useData<DefaultTheme.Config>()
|
const { theme } = useData<DefaultTheme.Config>()
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ const { theme } = useData<DefaultTheme.Config>()
|
|||||||
const replace = ref(false)
|
const replace = ref(false)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
replace.value = true
|
replace.value = true
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,43 +22,41 @@ onMounted(() => {
|
|||||||
* and navbar doesn't support using the VitePress data loading.
|
* and navbar doesn't support using the VitePress data loading.
|
||||||
*/
|
*/
|
||||||
const nav = computed(() => {
|
const nav = computed(() => {
|
||||||
if (!replace.value) {
|
if (!replace.value)
|
||||||
return theme.value.nav
|
return theme.value.nav
|
||||||
}
|
|
||||||
|
|
||||||
return theme.value.nav?.map((item) => {
|
return theme.value.nav?.map((item) => {
|
||||||
if (!item.text.includes("{app_version}")) {
|
if (!item.text.includes('{app_version}'))
|
||||||
return item
|
return item
|
||||||
}
|
|
||||||
|
|
||||||
const appVersion = release.stable.tag_name.substring(1)
|
const appVersion = release.stable.tag_name.substring(1)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
text: item.text.replace("{app_version}", appVersion),
|
text: item.text.replace('{app_version}', appVersion),
|
||||||
} satisfies DefaultTheme.NavItem
|
} satisfies DefaultTheme.NavItem
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<nav v-if="nav" aria-labelledby="main-nav-aria-label" class="VPNavBarMenu">
|
<nav v-if="nav" aria-labelledby="main-nav-aria-label" class="VPNavBarMenu">
|
||||||
<span id="main-nav-aria-label" class="visually-hidden">Main navigation</span>
|
<span id="main-nav-aria-label" class="visually-hidden">Main navigation</span>
|
||||||
<template v-for="item in nav" :key="item.text">
|
<template v-for="item in nav" :key="item.text">
|
||||||
<VPNavBarMenuLink v-if="'link' in item" :item="item" />
|
<VPNavBarMenuLink v-if="'link' in item" :item="item" />
|
||||||
<VPNavBarMenuGroup v-else :item="item" />
|
<VPNavBarMenuGroup v-else :item="item" />
|
||||||
</template>
|
</template>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.VPNavBarMenu {
|
.VPNavBarMenu {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width 768px) {
|
@media (min-width 768px) {
|
||||||
.VPNavBarMenu {
|
.VPNavBarMenu {
|
||||||
display: flex
|
display: flex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref } from "vue"
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { type DefaultTheme, useData } from "vitepress"
|
import { type DefaultTheme, useData } from 'vitepress'
|
||||||
|
|
||||||
import VPNavScreenMenuLink from "vitepress/dist/client/theme-default/components/VPNavScreenMenuLink.vue"
|
import VPNavScreenMenuLink from 'vitepress/dist/client/theme-default/components/VPNavScreenMenuLink.vue'
|
||||||
import VPNavScreenMenuGroup from "vitepress/dist/client/theme-default/components/VPNavScreenMenuGroup.vue"
|
import VPNavScreenMenuGroup from 'vitepress/dist/client/theme-default/components/VPNavScreenMenuGroup.vue'
|
||||||
|
|
||||||
import { data as release } from "../data/release.data"
|
import { data as release } from '../data/release.data'
|
||||||
|
|
||||||
const { theme } = useData<DefaultTheme.Config>()
|
const { theme } = useData<DefaultTheme.Config>()
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ const { theme } = useData<DefaultTheme.Config>()
|
|||||||
const replace = ref(false)
|
const replace = ref(false)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
replace.value = true
|
replace.value = true
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,37 +21,35 @@ onMounted(() => {
|
|||||||
* and navbar doesn't support using the VitePress data loading.
|
* and navbar doesn't support using the VitePress data loading.
|
||||||
*/
|
*/
|
||||||
const nav = computed(() => {
|
const nav = computed(() => {
|
||||||
if (!replace.value) {
|
if (!replace.value)
|
||||||
return theme.value.nav
|
return theme.value.nav
|
||||||
}
|
|
||||||
|
|
||||||
return theme.value.nav?.map((item) => {
|
return theme.value.nav?.map((item) => {
|
||||||
if (!item.text.includes("{app_version}")) {
|
if (!item.text.includes('{app_version}'))
|
||||||
return item
|
return item
|
||||||
}
|
|
||||||
|
|
||||||
const appVersion = release.stable.tag_name.substring(1)
|
const appVersion = release.stable.tag_name.substring(1)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
text: item.text.replace("{app_version}", appVersion),
|
text: item.text.replace('{app_version}', appVersion),
|
||||||
} satisfies DefaultTheme.NavItem
|
} satisfies DefaultTheme.NavItem
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<nav v-if="nav" class="VPNavScreenMenu">
|
<nav v-if="nav" class="VPNavScreenMenu">
|
||||||
<template v-for="item in nav" :key="item.text">
|
<template v-for="item in nav" :key="item.text">
|
||||||
<VPNavScreenMenuLink
|
<VPNavScreenMenuLink
|
||||||
v-if="'link' in item"
|
v-if="'link' in item"
|
||||||
:item="item"
|
:item="item"
|
||||||
/>
|
/>
|
||||||
<VPNavScreenMenuGroup
|
<VPNavScreenMenuGroup
|
||||||
v-else
|
v-else
|
||||||
:text="item.text || ''"
|
:text="item.text || ''"
|
||||||
:items="item.items"
|
:items="item.items"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
@ -15,7 +15,7 @@ const supportsViewTransition = ref(false)
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
supportsViewTransition.value = 'startViewTransition' in document
|
supportsViewTransition.value = 'startViewTransition' in document
|
||||||
&& window.matchMedia('(prefers-reduced-motion: no-preference)').matches
|
&& window.matchMedia('(prefers-reduced-motion: no-preference)').matches
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -40,35 +40,35 @@ onMounted(() => {
|
|||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.CustomSwitchAppearance {
|
.CustomSwitchAppearance {
|
||||||
display: flex
|
display: flex
|
||||||
justify-content: center
|
justify-content: center
|
||||||
align-items: center
|
align-items: center
|
||||||
width: 36px
|
width: 36px
|
||||||
height: 36px
|
height: 36px
|
||||||
color: var(--vp-c-text-2)
|
color: var(--vp-c-text-2)
|
||||||
transition: color 0.5s
|
transition: color 0.5s
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--vp-c-text-1)
|
color: var(--vp-c-text-1)
|
||||||
transition: color 0.25s
|
transition: color 0.25s
|
||||||
}
|
}
|
||||||
|
|
||||||
& > :deep(svg) {
|
& > :deep(svg) {
|
||||||
width: 20px
|
width: 20px
|
||||||
height: 20px
|
height: 20px
|
||||||
fill: currentColor
|
fill: currentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-view-transition="false"] {
|
&[data-view-transition="false"] {
|
||||||
.fade-enter-active,
|
.fade-enter-active,
|
||||||
.fade-leave-active {
|
.fade-leave-active {
|
||||||
transition: opacity 0.1s ease
|
transition: opacity 0.1s ease
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-enter-from,
|
.fade-enter-from,
|
||||||
.fade-leave-to {
|
.fade-leave-to {
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,174 +1,174 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
/// <reference types="@types/gtag.js" />
|
/// <reference types="@types/gtag.js" />
|
||||||
|
|
||||||
import { computed, onMounted, ref } from "vue"
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { data as release } from "../data/release.data"
|
import { data as release } from '../data/release.data'
|
||||||
|
|
||||||
const downloadInformation = computed(() => ({
|
const downloadInformation = computed(() => ({
|
||||||
preview: {
|
preview: {
|
||||||
tagName: release.preview.tag_name ?? "r0000",
|
tagName: release.preview.tag_name ?? 'r0000',
|
||||||
asset: (release.preview.assets ?? [])
|
asset: (release.preview.assets ?? [])
|
||||||
.find((a) => /^tachiyomi-r\d{4,}.apk/.test(a.name)),
|
.find(a => /^tachiyomi-r\d{4,}.apk/.test(a.name)),
|
||||||
},
|
},
|
||||||
stable: {
|
stable: {
|
||||||
tagName: release.stable.tag_name ?? "v0.00.0",
|
tagName: release.stable.tag_name ?? 'v0.00.0',
|
||||||
asset: (release.stable.assets ?? [])
|
asset: (release.stable.assets ?? [])
|
||||||
.find((a) => /^tachiyomi-v\d+\.\d+\.\d+.apk/.test(a.name)),
|
.find(a => /^tachiyomi-v\d+\.\d+\.\d+.apk/.test(a.name)),
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const isAndroid = ref(true)
|
const isAndroid = ref(true)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
isAndroid.value = !!navigator.userAgent.match(/android/i)
|
isAndroid.value = !!navigator.userAgent.match(/android/i)
|
||||||
})
|
})
|
||||||
|
|
||||||
function handleAnalytics(type: "preview" | "stable") {
|
function handleAnalytics(type: 'preview' | 'stable') {
|
||||||
window.gtag?.("event", "Download", {
|
window.gtag?.('event', 'Download', {
|
||||||
event_category: "App",
|
event_category: 'App',
|
||||||
event_label: type === "stable" ? "Stable" : "Preview",
|
event_label: type === 'stable' ? 'Stable' : 'Preview',
|
||||||
version: type === "stable"
|
version: type === 'stable'
|
||||||
? release.stable.tag_name
|
? release.stable.tag_name
|
||||||
: release.preview.tag_name,
|
: release.preview.tag_name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="!isAndroid" class="custom-block danger">
|
<div v-if="!isAndroid" class="custom-block danger">
|
||||||
<p class="custom-block-title">
|
<p class="custom-block-title">
|
||||||
Unsupported operating system
|
Unsupported operating system
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong>Tachiyomi</strong> is an <strong>Android app</strong> only.
|
<strong>Tachiyomi</strong> is an <strong>Android app</strong> only.
|
||||||
Use an <strong>Android device</strong> to download and install the app.
|
Use an <strong>Android device</strong> to download and install the app.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!isAndroid" class="custom-block warning">
|
<div v-if="!isAndroid" class="custom-block warning">
|
||||||
<p class="custom-block-title">
|
<p class="custom-block-title">
|
||||||
Caution
|
Caution
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Any app for any operating systems other than Android called
|
Any app for any operating systems other than Android called
|
||||||
<strong>Tachiyomi</strong> is not affiliated with this project.
|
<strong>Tachiyomi</strong> is not affiliated with this project.
|
||||||
</p>
|
</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
For more information, read the
|
For more information, read the
|
||||||
<a href="/docs/faq/general">General FAQ</a>.
|
<a href="/docs/faq/general">General FAQ</a>.
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</div>
|
</div>
|
||||||
<div class="download-buttons">
|
<div class="download-buttons">
|
||||||
<a
|
<a
|
||||||
class="download-button primary"
|
class="download-button primary"
|
||||||
:download="downloadInformation.stable.asset?.name"
|
:download="downloadInformation.stable.asset?.name"
|
||||||
:href="downloadInformation.stable.asset?.browser_download_url"
|
:href="downloadInformation.stable.asset?.browser_download_url"
|
||||||
@click="handleAnalytics('stable')"
|
@click="handleAnalytics('stable')"
|
||||||
>
|
>
|
||||||
<IconDownload />
|
<IconDownload />
|
||||||
<span class="text">Stable</span>
|
<span class="text">Stable</span>
|
||||||
<span class="version">{{ downloadInformation.stable.tagName }}</span>
|
<span class="version">{{ downloadInformation.stable.tagName }}</span>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="download-button secondary"
|
class="download-button secondary"
|
||||||
:download="downloadInformation.preview.asset?.name"
|
:download="downloadInformation.preview.asset?.name"
|
||||||
:href="downloadInformation.preview.asset?.browser_download_url"
|
:href="downloadInformation.preview.asset?.browser_download_url"
|
||||||
@click="handleAnalytics('preview')"
|
@click="handleAnalytics('preview')"
|
||||||
>
|
>
|
||||||
<IconBugReport />
|
<IconBugReport />
|
||||||
<span class="text">Preview</span>
|
<span class="text">Preview</span>
|
||||||
<span class="version">{{ downloadInformation.preview.tagName }}</span>
|
<span class="version">{{ downloadInformation.preview.tagName }}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<span class="version-disclaimer">
|
<span class="version-disclaimer">
|
||||||
Requires <strong>Android 6.0</strong> or higher.
|
Requires <strong>Android 6.0</strong> or higher.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.download-buttons {
|
.download-buttons {
|
||||||
display: flex
|
display: flex
|
||||||
gap: 0.75em
|
gap: 0.75em
|
||||||
justify-content: center
|
justify-content: center
|
||||||
align-items: center
|
align-items: center
|
||||||
margin: 0.75em auto
|
margin: 0.75em auto
|
||||||
}
|
}
|
||||||
|
|
||||||
.download-button {
|
.download-button {
|
||||||
display: inline-block
|
display: inline-block
|
||||||
border: 1px solid transparent
|
border: 1px solid transparent
|
||||||
text-align: center
|
text-align: center
|
||||||
font-weight: 600
|
font-weight: 600
|
||||||
white-space: nowrap
|
white-space: nowrap
|
||||||
transition: color 0.25s, border-color 0.25s, background-color 0.25s
|
transition: color 0.25s, border-color 0.25s, background-color 0.25s
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
transition: all 0.3s ease
|
transition: all 0.3s ease
|
||||||
border-radius: 20px
|
border-radius: 20px
|
||||||
padding: 0 20px
|
padding: 0 20px
|
||||||
line-height: 38px
|
line-height: 38px
|
||||||
font-size: 14px
|
font-size: 14px
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: none !important
|
text-decoration: none !important
|
||||||
}
|
}
|
||||||
|
|
||||||
&.primary {
|
&.primary {
|
||||||
border-color: var(--vp-button-brand-border)
|
border-color: var(--vp-button-brand-border)
|
||||||
color: var(--vp-button-brand-text)
|
color: var(--vp-button-brand-text)
|
||||||
background-color: var(--vp-button-brand-bg)
|
background-color: var(--vp-button-brand-bg)
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: var(--vp-button-brand-hover-border)
|
border-color: var(--vp-button-brand-hover-border)
|
||||||
color: var(--vp-button-brand-hover-text)
|
color: var(--vp-button-brand-hover-text)
|
||||||
background-color: var(--vp-button-brand-hover-bg)
|
background-color: var(--vp-button-brand-hover-bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
border-color: var(--vp-button-brand-active-border)
|
border-color: var(--vp-button-brand-active-border)
|
||||||
color: var(--vp-button-brand-active-text)
|
color: var(--vp-button-brand-active-text)
|
||||||
background-color: var(--vp-button-brand-active-bg)
|
background-color: var(--vp-button-brand-active-bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.secondary {
|
&.secondary {
|
||||||
border-color: var(--vp-button-alt-border)
|
border-color: var(--vp-button-alt-border)
|
||||||
color: var(--vp-button-alt-text)
|
color: var(--vp-button-alt-text)
|
||||||
background-color: var(--vp-button-alt-bg)
|
background-color: var(--vp-button-alt-bg)
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: var(--vp-button-alt-hover-border)
|
border-color: var(--vp-button-alt-hover-border)
|
||||||
color: var(--vp-button-alt-hover-text)
|
color: var(--vp-button-alt-hover-text)
|
||||||
background-color: var(--vp-button-alt-hover-bg)
|
background-color: var(--vp-button-alt-hover-bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
border-color: var(--vp-button-alt-active-border)
|
border-color: var(--vp-button-alt-active-border)
|
||||||
color: var(--vp-button-alt-active-text)
|
color: var(--vp-button-alt-active-text)
|
||||||
background-color: var(--vp-button-alt-active-bg)
|
background-color: var(--vp-button-alt-active-bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
display: inline-block
|
display: inline-block
|
||||||
vertical-align: middle
|
vertical-align: middle
|
||||||
margin-right: 0.5em
|
margin-right: 0.5em
|
||||||
font-size: 1.25em
|
font-size: 1.25em
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
margin-right: 10px
|
margin-right: 10px
|
||||||
}
|
}
|
||||||
|
|
||||||
.version {
|
.version {
|
||||||
font-size: 0.8em
|
font-size: 0.8em
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-disclaimer {
|
.version-disclaimer {
|
||||||
display: block
|
display: block
|
||||||
text-align: center
|
text-align: center
|
||||||
margin: 0.75em auto
|
margin: 0.75em auto
|
||||||
font-size: 0.75rem
|
font-size: 0.75rem
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,104 +1,104 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, toRefs } from "vue"
|
import { computed, toRefs } from 'vue'
|
||||||
import { useMediaQuery } from "@vueuse/core"
|
import { useMediaQuery } from '@vueuse/core'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ElForm,
|
ElForm,
|
||||||
ElFormItem,
|
ElFormItem,
|
||||||
ElInput,
|
ElInput,
|
||||||
ElOption,
|
ElOption,
|
||||||
ElRadio,
|
ElRadio,
|
||||||
ElRadioGroup,
|
ElRadioGroup,
|
||||||
ElSelect,
|
ElSelect,
|
||||||
} from "element-plus"
|
} from 'element-plus'
|
||||||
|
|
||||||
import { langName, simpleLangName } from "../../../config/scripts/languages"
|
import { langName, simpleLangName } from '../../../config/scripts/languages'
|
||||||
import type { Extension } from "../../queries/useExtensionsRepositoryQuery"
|
import type { Extension } from '../../queries/useExtensionsRepositoryQuery'
|
||||||
|
|
||||||
export type Nsfw = "Show all" | "NSFW" | "SFW"
|
export type Nsfw = 'Show all' | 'NSFW' | 'SFW'
|
||||||
export type Sort = "Ascending" | "Descending"
|
export type Sort = 'Ascending' | 'Descending'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
extensions: Extension[][]
|
extensions: Extension[][]
|
||||||
search: string
|
search: string
|
||||||
lang: string[]
|
lang: string[]
|
||||||
nsfw: Nsfw
|
nsfw: Nsfw
|
||||||
sort: Sort
|
sort: Sort
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
(e: "update:search", search: string): void
|
(e: 'update:search', search: string): void
|
||||||
(e: "update:lang", lang: string[]): void
|
(e: 'update:lang', lang: string[]): void
|
||||||
(e: "update:nsfw", nsfw: Nsfw): void
|
(e: 'update:nsfw', nsfw: Nsfw): void
|
||||||
(e: "update:sort", sort: Sort): void
|
(e: 'update:sort', sort: Sort): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { extensions } = toRefs(props)
|
const { extensions } = toRefs(props)
|
||||||
|
|
||||||
const isSmallScreen = useMediaQuery("(max-width: 767px)")
|
const isSmallScreen = useMediaQuery('(max-width: 767px)')
|
||||||
const labelPosition = computed(() => isSmallScreen.value ? "top" : "right")
|
const labelPosition = computed(() => isSmallScreen.value ? 'top' : 'right')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<div class="filters-list">
|
<div class="filters-list">
|
||||||
<ElForm label-width="120px" :label-position="labelPosition">
|
<ElForm label-width="120px" :label-position="labelPosition">
|
||||||
<ElFormItem label="Search:">
|
<ElFormItem label="Search:">
|
||||||
<ElInput
|
<ElInput
|
||||||
:model-value="search"
|
:model-value="search"
|
||||||
placeholder="Search extensions by name or ID..."
|
placeholder="Search extensions by name or ID..."
|
||||||
clearable
|
clearable
|
||||||
@update:model-value="$emit('update:search', $event)"
|
@update:model-value="$emit('update:search', $event)"
|
||||||
/>
|
/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="Languages:">
|
<ElFormItem label="Languages:">
|
||||||
<ElSelect
|
<ElSelect
|
||||||
:model-value="lang"
|
:model-value="lang"
|
||||||
placeholder="Show specific languages..."
|
placeholder="Show specific languages..."
|
||||||
multiple
|
multiple
|
||||||
clearable
|
clearable
|
||||||
@update:model-value="$emit('update:lang', $event)"
|
@update:model-value="$emit('update:lang', $event)"
|
||||||
>
|
>
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="[group] in extensions"
|
v-for="[group] in extensions"
|
||||||
:key="group.lang"
|
:key="group.lang"
|
||||||
:label="group.lang === 'en' ? simpleLangName(group.lang) : langName(group.lang)"
|
:label="group.lang === 'en' ? simpleLangName(group.lang) : langName(group.lang)"
|
||||||
:value="group.lang"
|
:value="group.lang"
|
||||||
/>
|
/>
|
||||||
</ElSelect>
|
</ElSelect>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="Sort by:">
|
<ElFormItem label="Sort by:">
|
||||||
<ElRadioGroup
|
<ElRadioGroup
|
||||||
:model-value="sort"
|
:model-value="sort"
|
||||||
@update:model-value="$emit('update:sort', $event)"
|
@update:model-value="$emit('update:sort', $event)"
|
||||||
>
|
>
|
||||||
<ElRadio label="Ascending" />
|
<ElRadio label="Ascending" />
|
||||||
<ElRadio label="Descending" />
|
<ElRadio label="Descending" />
|
||||||
</ElRadioGroup>
|
</ElRadioGroup>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="Display mode:">
|
<ElFormItem label="Display mode:">
|
||||||
<ElRadioGroup
|
<ElRadioGroup
|
||||||
:model-value="nsfw"
|
:model-value="nsfw"
|
||||||
@update:model-value="$emit('update:nsfw', $event)"
|
@update:model-value="$emit('update:nsfw', $event)"
|
||||||
>
|
>
|
||||||
<ElRadio label="NSFW" />
|
<ElRadio label="NSFW" />
|
||||||
<ElRadio label="SFW" />
|
<ElRadio label="SFW" />
|
||||||
<ElRadio label="Show all" />
|
<ElRadio label="Show all" />
|
||||||
</ElRadioGroup>
|
</ElRadioGroup>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElForm>
|
</ElForm>
|
||||||
</div>
|
</div>
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.filters-list {
|
.filters-list {
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
row-gap: 1rem
|
row-gap: 1rem
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-select {
|
.el-select {
|
||||||
width: 100%
|
width: 100%
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,51 +1,51 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, toRefs } from "vue"
|
import { computed, toRefs } from 'vue'
|
||||||
import { langName, simpleLangName } from "../../../config/scripts/languages"
|
import { langName, simpleLangName } from '../../../config/scripts/languages'
|
||||||
import type { Extension } from "../../queries/useExtensionsRepositoryQuery"
|
import type { Extension } from '../../queries/useExtensionsRepositoryQuery'
|
||||||
import ExtensionItem from "./ExtensionItem.vue"
|
import ExtensionItem from './ExtensionItem.vue'
|
||||||
|
|
||||||
const props = defineProps<{ list: Extension[]; totalCount: number }>()
|
const props = defineProps<{ list: Extension[]; totalCount: number }>()
|
||||||
const { list } = toRefs(props)
|
const { list } = toRefs(props)
|
||||||
|
|
||||||
const groupName = computed(() => {
|
const groupName = computed(() => {
|
||||||
const firstItem = list.value[0]
|
const firstItem = list.value[0]
|
||||||
|
|
||||||
return firstItem.lang === "en"
|
return firstItem.lang === 'en'
|
||||||
? simpleLangName(firstItem.lang)
|
? simpleLangName(firstItem.lang)
|
||||||
: langName(firstItem.lang)
|
: langName(firstItem.lang)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="extension-group">
|
<div class="extension-group">
|
||||||
<h2>
|
<h2>
|
||||||
<span>{{ groupName }}</span>
|
<span>{{ groupName }}</span>
|
||||||
|
|
||||||
<span class="extensions-total">
|
<span class="extensions-total">
|
||||||
Total:
|
Total:
|
||||||
<span class="extensions-total-sum">
|
<span class="extensions-total-sum">
|
||||||
{{ totalCount }}
|
{{ totalCount }}
|
||||||
</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.', '')"
|
||||||
:key="extension.apk"
|
:key="extension.apk"
|
||||||
:item="extension"
|
:item="extension"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.extension-group h2 {
|
.extension-group h2 {
|
||||||
display: flex
|
display: flex
|
||||||
align-items: center
|
align-items: center
|
||||||
justify-content: space-between
|
justify-content: space-between
|
||||||
|
|
||||||
.extensions-total-sum {
|
.extensions-total-sum {
|
||||||
color: var(--vp-c-brand)
|
color: var(--vp-c-brand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,179 +1,179 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
/// <reference types="@types/gtag.js" />
|
/// <reference types="@types/gtag.js" />
|
||||||
|
|
||||||
import { computed, toRefs } from "vue"
|
import { computed, toRefs } from 'vue'
|
||||||
import type { Extension } from "../../queries/useExtensionsRepositoryQuery"
|
import type { Extension } from '../../queries/useExtensionsRepositoryQuery'
|
||||||
|
|
||||||
const props = defineProps<{ item: Extension }>()
|
const props = defineProps<{ item: Extension }>()
|
||||||
const { item } = toRefs(props)
|
const { item } = toRefs(props)
|
||||||
|
|
||||||
const pkgId = computed(() => {
|
const pkgId = computed(() => {
|
||||||
return item.value.pkg.replace("eu.kanade.tachiyomi.extension.", "")
|
return item.value.pkg.replace('eu.kanade.tachiyomi.extension.', '')
|
||||||
})
|
})
|
||||||
|
|
||||||
const pkgName = computed(() => item.value.name.split(": ")[1])
|
const pkgName = computed(() => item.value.name.split(': ')[1])
|
||||||
const pkgIsNsfw = computed(() => item.value.nsfw === 1)
|
const pkgIsNsfw = computed(() => item.value.nsfw === 1)
|
||||||
|
|
||||||
const iconUrl = computed(() => {
|
const iconUrl = computed(() => {
|
||||||
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/icon/${item.value.pkg}.png`
|
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/icon/${item.value.pkg}.png`
|
||||||
})
|
})
|
||||||
|
|
||||||
const apkUrl = computed(() => {
|
const apkUrl = computed(() => {
|
||||||
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/apk/${item.value.apk}`
|
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/apk/${item.value.apk}`
|
||||||
})
|
})
|
||||||
|
|
||||||
function handleAnalytics() {
|
function handleAnalytics() {
|
||||||
window.gtag?.("event", "Download", {
|
window.gtag?.('event', 'Download', {
|
||||||
event_category: "Extension",
|
event_category: 'Extension',
|
||||||
event_label: pkgName.value,
|
event_label: pkgName.value,
|
||||||
version: item.value.version,
|
version: item.value.version,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="extension" tabindex="-1">
|
<div class="extension" tabindex="-1">
|
||||||
<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">
|
||||||
<div class="upper">
|
<div class="upper">
|
||||||
{{ pkgName }}
|
{{ pkgName }}
|
||||||
</div>
|
</div>
|
||||||
<div class="lower">
|
<div class="lower">
|
||||||
{{ pkgId }}
|
{{ pkgId }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Badge v-if="pkgIsNsfw" type="danger" :text="item.version" 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="item.version" 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
|
<a
|
||||||
:href="apkUrl"
|
:href="apkUrl"
|
||||||
class="extension-download"
|
class="extension-download"
|
||||||
title="Download APK"
|
title="Download APK"
|
||||||
:download="item.apk"
|
:download="item.apk"
|
||||||
@click="handleAnalytics"
|
@click="handleAnalytics"
|
||||||
>
|
>
|
||||||
↓
|
↓
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.extension {
|
.extension {
|
||||||
position: relative
|
position: relative
|
||||||
align-items: center
|
align-items: center
|
||||||
display: flex
|
display: flex
|
||||||
width: calc(100% + 1em)
|
width: calc(100% + 1em)
|
||||||
padding: 0.5em
|
padding: 0.5em
|
||||||
margin: 0.8em -0.5em
|
margin: 0.8em -0.5em
|
||||||
border-radius: 8px
|
border-radius: 8px
|
||||||
gap: 0.675rem
|
gap: 0.675rem
|
||||||
scroll-margin-top: calc(var(--vp-nav-height) + 24px)
|
scroll-margin-top: calc(var(--vp-nav-height) + 24px)
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--vp-c-bg-soft)
|
background-color: var(--vp-c-bg-soft)
|
||||||
}
|
}
|
||||||
|
|
||||||
&:target,
|
&:target,
|
||||||
&:focus {
|
&:focus {
|
||||||
background-color: var(--vp-c-brand-soft)
|
background-color: var(--vp-c-brand-soft)
|
||||||
border-radius: 8px
|
border-radius: 8px
|
||||||
transition: 500ms background-color
|
transition: 500ms background-color
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none
|
outline: none
|
||||||
}
|
}
|
||||||
|
|
||||||
.anchor {
|
.anchor {
|
||||||
position: absolute
|
position: absolute
|
||||||
left: 0
|
left: 0
|
||||||
margin-left: -1em
|
margin-left: -1em
|
||||||
font-size: 1.4em
|
font-size: 1.4em
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover .anchor,
|
&:hover .anchor,
|
||||||
.anchor:focus-visible {
|
.anchor:focus-visible {
|
||||||
opacity: 1
|
opacity: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-icon {
|
.extension-icon {
|
||||||
flex-shrink: 0
|
flex-shrink: 0
|
||||||
margin-left: -4px
|
margin-left: -4px
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-text {
|
.extension-text {
|
||||||
flex-grow: 1
|
flex-grow: 1
|
||||||
min-width: 0
|
min-width: 0
|
||||||
|
|
||||||
.upper {
|
.upper {
|
||||||
color: var(--vp-c-text-1)
|
color: var(--vp-c-text-1)
|
||||||
font-weight: 600
|
font-weight: 600
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
text-overflow: ellipsis
|
text-overflow: ellipsis
|
||||||
white-space: nowrap
|
white-space: nowrap
|
||||||
|
|
||||||
.badge {
|
.badge {
|
||||||
font-weight: 400
|
font-weight: 400
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.lower {
|
.lower {
|
||||||
color: var(--vp-c-text-2)
|
color: var(--vp-c-text-2)
|
||||||
font-family: var(--vp-font-family-mono)
|
font-family: var(--vp-font-family-mono)
|
||||||
font-size: 0.75rem
|
font-size: 0.75rem
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
text-overflow: ellipsis
|
text-overflow: ellipsis
|
||||||
white-space: nowrap
|
white-space: nowrap
|
||||||
line-height: 1rem
|
line-height: 1rem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-download {
|
.extension-download {
|
||||||
padding: 0.4em
|
padding: 0.4em
|
||||||
font-weight: 700
|
font-weight: 700
|
||||||
font-size: 1.4em
|
font-size: 1.4em
|
||||||
border-radius: 4px
|
border-radius: 4px
|
||||||
flex-shrink: 0
|
flex-shrink: 0
|
||||||
margin-right: -0.4em
|
margin-right: -0.4em
|
||||||
|
|
||||||
.material-icons {
|
.material-icons {
|
||||||
color: white
|
color: white
|
||||||
max-width: 18px
|
max-width: 18px
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.VPBadge {
|
.VPBadge {
|
||||||
background-color: var(--vp-c-brand-darker)
|
background-color: var(--vp-c-brand-darker)
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width 767px) {
|
@media (max-width 767px) {
|
||||||
padding: 0.4em 0
|
padding: 0.4em 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width 767px) {
|
@media (max-width 767px) {
|
||||||
.anchor {
|
.anchor {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
|
||||||
.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
|
padding: 0.5em
|
||||||
margin: 0.8em 0
|
margin: 0.8em 0
|
||||||
width: 100%
|
width: 100%
|
||||||
|
|
||||||
.extension-icon {
|
.extension-icon {
|
||||||
margin-left: 0
|
margin-left: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-download {
|
.extension-download {
|
||||||
margin-right: 0
|
margin-right: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,36 +1,36 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, toRefs } from "vue"
|
import { computed, toRefs } from 'vue'
|
||||||
import type { Extension } from "../../queries/useExtensionsRepositoryQuery"
|
import type { Extension } from '../../queries/useExtensionsRepositoryQuery'
|
||||||
import ExtensionGroup from "./ExtensionGroup.vue"
|
import ExtensionGroup from './ExtensionGroup.vue'
|
||||||
|
|
||||||
const props = defineProps<{ extensions: Extension[][] }>()
|
const props = defineProps<{ extensions: Extension[][] }>()
|
||||||
const { extensions } = toRefs(props)
|
const { extensions } = toRefs(props)
|
||||||
|
|
||||||
const totalCount = computed(() => {
|
const totalCount = computed(() => {
|
||||||
return extensions.value.reduce((sum, item) => sum + item.length, 0)
|
return extensions.value.reduce((sum, item) => sum + item.length, 0)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="extension-list">
|
<div class="extension-list">
|
||||||
<ExtensionGroup
|
<ExtensionGroup
|
||||||
v-for="group in extensions"
|
v-for="group in extensions"
|
||||||
:key="group[0].lang"
|
:key="group[0].lang"
|
||||||
:list="group"
|
:list="group"
|
||||||
:class="group[0].lang"
|
:class="group[0].lang"
|
||||||
:total-count="totalCount"
|
:total-count="totalCount"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.extension-list {
|
.extension-list {
|
||||||
> div {
|
> div {
|
||||||
&:not(:first-of-type) {
|
&:not(:first-of-type) {
|
||||||
.extensions-total {
|
.extensions-total {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,127 +1,125 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import groupBy from "lodash.groupby"
|
import groupBy from 'lodash.groupby'
|
||||||
import { ElLoading } from "element-plus"
|
import { ElLoading } from 'element-plus'
|
||||||
|
|
||||||
import { computed, nextTick, onMounted, reactive, ref, watch } from "vue"
|
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
|
||||||
import { simpleLangName } from "../../../config/scripts/languages"
|
import { simpleLangName } from '../../../config/scripts/languages'
|
||||||
import useExtensionsRepositoryQuery from "../../queries/useExtensionsRepositoryQuery"
|
import useExtensionsRepositoryQuery from '../../queries/useExtensionsRepositoryQuery'
|
||||||
import type { Extension } from "../../queries/useExtensionsRepositoryQuery"
|
import type { Extension } from '../../queries/useExtensionsRepositoryQuery'
|
||||||
import ExtensionFilters from "./ExtensionFilters.vue"
|
import ExtensionFilters from './ExtensionFilters.vue'
|
||||||
import ExtensionList from "./ExtensionList.vue"
|
import ExtensionList from './ExtensionList.vue'
|
||||||
import type { Nsfw, Sort } from "./ExtensionFilters.vue"
|
import type { Nsfw, Sort } from './ExtensionFilters.vue'
|
||||||
|
|
||||||
const { data: extensions, isLoading } = useExtensionsRepositoryQuery({
|
const { data: extensions, isLoading } = useExtensionsRepositoryQuery({
|
||||||
select: (response) => {
|
select: (response) => {
|
||||||
const values: Extension[][] = Object.values(groupBy(response, "lang"))
|
const values: Extension[][] = Object.values(groupBy(response, 'lang'))
|
||||||
values.sort(languageComparator)
|
values.sort(languageComparator)
|
||||||
|
|
||||||
return values
|
return values
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const filters = reactive({
|
const filters = reactive({
|
||||||
search: "",
|
search: '',
|
||||||
lang: [] as string[],
|
lang: [] as string[],
|
||||||
nsfw: "Show all" as Nsfw,
|
nsfw: 'Show all' as Nsfw,
|
||||||
sort: "Ascending" as Sort,
|
sort: 'Ascending' as Sort,
|
||||||
})
|
})
|
||||||
|
|
||||||
function languageComparator(a: Extension[], b: Extension[]) {
|
function languageComparator(a: Extension[], b: Extension[]) {
|
||||||
const langA = simpleLangName(a[0].lang)
|
const langA = simpleLangName(a[0].lang)
|
||||||
const langB = simpleLangName(b[0].lang)
|
const langB = simpleLangName(b[0].lang)
|
||||||
if (langA === "All" && langB === "English") {
|
if (langA === 'All' && langB === 'English')
|
||||||
return -1
|
return -1
|
||||||
}
|
|
||||||
if (langA === "English" && langB === "All") {
|
if (langA === 'English' && langB === 'All')
|
||||||
return 1
|
return 1
|
||||||
}
|
|
||||||
if (langA === "English") {
|
if (langA === 'English')
|
||||||
return -1
|
return -1
|
||||||
}
|
|
||||||
if (langB === "English") {
|
if (langB === 'English')
|
||||||
return 1
|
return 1
|
||||||
}
|
|
||||||
if (langA < langB) {
|
if (langA < langB)
|
||||||
return -1
|
return -1
|
||||||
}
|
|
||||||
if (langA > langB) {
|
if (langA > langB)
|
||||||
return 1
|
return 1
|
||||||
}
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredExtensions = computed(() => {
|
const filteredExtensions = computed(() => {
|
||||||
const filtered: Extension[][] = []
|
const filtered: Extension[][] = []
|
||||||
|
|
||||||
for (const group of (extensions.value ?? [])) {
|
for (const group of (extensions.value ?? [])) {
|
||||||
let filteredGroup = filters.lang.length
|
let filteredGroup = filters.lang.length
|
||||||
? (filters.lang.includes(group[0].lang) ? group : [])
|
? (filters.lang.includes(group[0].lang) ? group : [])
|
||||||
: group
|
: group
|
||||||
|
|
||||||
if (filters.search) {
|
if (filters.search) {
|
||||||
filteredGroup = filteredGroup.filter(
|
filteredGroup = filteredGroup.filter(
|
||||||
(ext) =>
|
ext =>
|
||||||
ext.name.toLowerCase().includes(filters.search.toLowerCase())
|
ext.name.toLowerCase().includes(filters.search.toLowerCase())
|
||||||
|| ext.sources.some((source) => source.id.includes(filters.search)),
|
|| ext.sources.some(source => source.id.includes(filters.search)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
filteredGroup = filteredGroup.filter((ext) =>
|
filteredGroup = filteredGroup.filter(ext =>
|
||||||
filters.nsfw === "Show all" ? true : ext.nsfw === (filters.nsfw === "NSFW" ? 1 : 0),
|
filters.nsfw === 'Show all' ? true : ext.nsfw === (filters.nsfw === 'NSFW' ? 1 : 0),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (filters.sort && filters.sort === "Descending") {
|
if (filters.sort && filters.sort === 'Descending')
|
||||||
filteredGroup = filteredGroup.reverse()
|
filteredGroup = filteredGroup.reverse()
|
||||||
}
|
|
||||||
if (filteredGroup.length) {
|
|
||||||
filtered.push(filteredGroup)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered
|
if (filteredGroup.length)
|
||||||
|
filtered.push(filteredGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered
|
||||||
})
|
})
|
||||||
|
|
||||||
const loadingInstance = ref<ReturnType<typeof ElLoading["service"]>>()
|
const loadingInstance = ref<ReturnType<typeof ElLoading['service']>>()
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadingInstance.value = ElLoading.service({
|
loadingInstance.value = ElLoading.service({
|
||||||
target: ".extensions",
|
target: '.extensions',
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
background: "transparent",
|
background: 'transparent',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(extensions, async () => {
|
watch(extensions, async () => {
|
||||||
if (window.location.hash) {
|
if (window.location.hash) {
|
||||||
await nextTick()
|
await nextTick()
|
||||||
const extElement = document.getElementById(window.location.hash.substring(1))
|
const extElement = document.getElementById(window.location.hash.substring(1))
|
||||||
|
|
||||||
extElement?.scrollIntoView({ behavior: "smooth" })
|
extElement?.scrollIntoView({ behavior: 'smooth' })
|
||||||
extElement?.focus({ preventScroll: true })
|
extElement?.focus({ preventScroll: true })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
watch([isLoading, loadingInstance], async ([newIsLoading]) => {
|
watch([isLoading, loadingInstance], async ([newIsLoading]) => {
|
||||||
if (!newIsLoading) {
|
if (!newIsLoading)
|
||||||
loadingInstance.value?.close()
|
loadingInstance.value?.close()
|
||||||
}
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ExtensionFilters
|
<ExtensionFilters
|
||||||
v-model:search="filters.search"
|
v-model:search="filters.search"
|
||||||
v-model:lang="filters.lang"
|
v-model:lang="filters.lang"
|
||||||
v-model:nsfw="filters.nsfw"
|
v-model:nsfw="filters.nsfw"
|
||||||
v-model:sort="filters.sort"
|
v-model:sort="filters.sort"
|
||||||
:extensions="extensions ?? []"
|
:extensions="extensions ?? []"
|
||||||
/>
|
/>
|
||||||
<div class="extensions">
|
<div class="extensions">
|
||||||
<ExtensionList v-if="!isLoading" :extensions="filteredExtensions" />
|
<ExtensionList v-if="!isLoading" :extensions="filteredExtensions" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.extensions {
|
.extensions {
|
||||||
min-height: 200px
|
min-height: 200px
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,161 +1,161 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { IconChevronRight } from "@iconify-prerendered/vue-mdi"
|
import { IconChevronRight } from '@iconify-prerendered/vue-mdi'
|
||||||
import { data as newsList } from "../data/news.data"
|
import { data as newsList } from '../data/news.data'
|
||||||
|
|
||||||
const dateFormatter = new Intl.DateTimeFormat("en", {
|
const dateFormatter = new Intl.DateTimeFormat('en', {
|
||||||
dateStyle: "medium",
|
dateStyle: 'medium',
|
||||||
timeZone: "UTC",
|
timeZone: 'UTC',
|
||||||
})
|
})
|
||||||
|
|
||||||
function formatDate(date: string) {
|
function formatDate(date: string) {
|
||||||
const [year, month, day] = date
|
const [year, month, day] = date
|
||||||
.substring(0, 10)
|
.substring(0, 10)
|
||||||
.split("-")
|
.split('-')
|
||||||
.map((number) => Number.parseInt(number, 10))
|
.map(number => Number.parseInt(number, 10))
|
||||||
const utcDate = Date.UTC(year, month - 1, day)
|
const utcDate = Date.UTC(year, month - 1, day)
|
||||||
return dateFormatter.format(utcDate)
|
return dateFormatter.format(utcDate)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<article
|
<article
|
||||||
v-for="news of newsList"
|
v-for="news of newsList"
|
||||||
:key="news.url"
|
:key="news.url"
|
||||||
class="news"
|
class="news"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<h3>
|
<h3>
|
||||||
<a :href="news.url">
|
<a :href="news.url">
|
||||||
<span class="hover" />
|
<span class="hover" />
|
||||||
<span class="title">{{ news.title }}</span>
|
<span class="title">{{ news.title }}</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="background" />
|
<div class="background" />
|
||||||
</h3>
|
</h3>
|
||||||
<time :datetime="news.date">
|
<time :datetime="news.date">
|
||||||
{{ formatDate(news.date) }}
|
{{ formatDate(news.date) }}
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
<p>{{ news.description }}</p>
|
<p>{{ news.description }}</p>
|
||||||
<div class="readPrompt" aria-hidden="true">
|
<div class="readPrompt" aria-hidden="true">
|
||||||
<span>Read article</span>
|
<span>Read article</span>
|
||||||
<IconChevronRight />
|
<IconChevronRight />
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.news {
|
.news {
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
gap: 0.5rem
|
gap: 0.5rem
|
||||||
position: relative
|
position: relative
|
||||||
|
|
||||||
&:first-of-type {
|
&:first-of-type {
|
||||||
margin-top: 3rem
|
margin-top: 3rem
|
||||||
}
|
}
|
||||||
|
|
||||||
& + .news {
|
& + .news {
|
||||||
margin-top: 3rem
|
margin-top: 3rem
|
||||||
}
|
}
|
||||||
|
|
||||||
time {
|
time {
|
||||||
font-size: 0.875rem
|
font-size: 0.875rem
|
||||||
line-height: 1.25rem
|
line-height: 1.25rem
|
||||||
color: var(--vp-c-text-2)
|
color: var(--vp-c-text-2)
|
||||||
z-index: 10
|
z-index: 10
|
||||||
}
|
}
|
||||||
|
|
||||||
h3,
|
h3,
|
||||||
p {
|
p {
|
||||||
margin: 0
|
margin: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
position: unset
|
position: unset
|
||||||
font-size: 1.125rem
|
font-size: 1.125rem
|
||||||
line-height: 1.75rem
|
line-height: 1.75rem
|
||||||
letter-spacing: -0.025em
|
letter-spacing: -0.025em
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 a {
|
h3 a {
|
||||||
font-weight: 600
|
font-weight: 600
|
||||||
color: var(--vp-c-text-1)
|
color: var(--vp-c-text-1)
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--vp-c-text-1)
|
color: var(--vp-c-text-1)
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none
|
outline: none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.title,
|
.title,
|
||||||
.readPrompt,
|
.readPrompt,
|
||||||
p,
|
p,
|
||||||
time {
|
time {
|
||||||
position: relative
|
position: relative
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
z-index: 10
|
z-index: 10
|
||||||
}
|
}
|
||||||
|
|
||||||
.readPrompt {
|
.readPrompt {
|
||||||
font-weight: 500
|
font-weight: 500
|
||||||
font-size: 0.875rem
|
font-size: 0.875rem
|
||||||
line-height: 1.25rem
|
line-height: 1.25rem
|
||||||
color: var(--vp-c-brand-1)
|
color: var(--vp-c-brand-1)
|
||||||
display: flex
|
display: flex
|
||||||
align-items: center
|
align-items: center
|
||||||
margin-top: 0.25rem
|
margin-top: 0.25rem
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
margin-bottom: -2px
|
margin-bottom: -2px
|
||||||
margin-left: 0.25rem
|
margin-left: 0.25rem
|
||||||
width: 1.25rem
|
width: 1.25rem
|
||||||
height: 1.25rem
|
height: 1.25rem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover,
|
.hover,
|
||||||
.background {
|
.background {
|
||||||
position: absolute
|
position: absolute
|
||||||
z-index: 20
|
z-index: 20
|
||||||
bottom: -1rem
|
bottom: -1rem
|
||||||
top: -1rem
|
top: -1rem
|
||||||
left: -1rem
|
left: -1rem
|
||||||
right: -1rem
|
right: -1rem
|
||||||
border-radius: 12px
|
border-radius: 12px
|
||||||
}
|
}
|
||||||
|
|
||||||
.background {
|
.background {
|
||||||
background-color: var(--vp-c-bg-soft)
|
background-color: var(--vp-c-bg-soft)
|
||||||
transform: scale(0.95)
|
transform: scale(0.95)
|
||||||
opacity: 0
|
opacity: 0
|
||||||
z-index: 0
|
z-index: 0
|
||||||
transition: opacity 0.15s cubic-bezier(0.4, 0, 0.2, 1), transform 0.15s cubic-bezier(0.4, 0, 0.2, 1)
|
transition: opacity 0.15s cubic-bezier(0.4, 0, 0.2, 1), transform 0.15s cubic-bezier(0.4, 0, 0.2, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover .background,
|
&:hover .background,
|
||||||
&:focus-within .background {
|
&:focus-within .background {
|
||||||
opacity: 1
|
opacity: 1
|
||||||
transform: scale(1)
|
transform: scale(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
h3: a
|
h3: a
|
||||||
|
|
||||||
:focus-visible + .background {
|
:focus-visible + .background {
|
||||||
outline: 2px solid var(--vp-c-brand-2)
|
outline: 2px solid var(--vp-c-brand-2)
|
||||||
}
|
}
|
||||||
|
|
||||||
:focus-visible + .background {
|
:focus-visible + .background {
|
||||||
outline: 2px solid var(--vp-c-brand-2)
|
outline: 2px solid var(--vp-c-brand-2)
|
||||||
}
|
}
|
||||||
|
|
||||||
:focus-visible + .background {
|
:focus-visible + .background {
|
||||||
outline: 2px solid var(--vp-c-brand-2)
|
outline: 2px solid var(--vp-c-brand-2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -3,30 +3,30 @@ defineProps<{ title: string; description?: string; dir?: string }>()
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
tw="w-full h-full bg-white flex flex-col"
|
tw="w-full h-full bg-white flex flex-col"
|
||||||
style="background:linear-gradient(0deg, rgba(255, 255, 255, 0.92), rgba(231,230,255,0.86)), url(https://tachiyomi.org/img/open-graph-background.png)"
|
style="background:linear-gradient(0deg, rgba(255, 255, 255, 0.92), rgba(231,230,255,0.86)), url(https://tachiyomi.org/img/open-graph-background.png)"
|
||||||
>
|
>
|
||||||
<div tw="p-10 w-full min-h-0 grow flex flex-col items-center justify-between">
|
<div tw="p-10 w-full min-h-0 grow flex flex-col items-center justify-between">
|
||||||
<div tw="w-full flex justify-between items-center text-4xl font-medium">
|
<div tw="w-full flex justify-between items-center text-4xl font-medium">
|
||||||
<div tw="flex items-center">
|
<div tw="flex items-center">
|
||||||
<svg width="64" height="64" viewBox="0 0 288 288" preserveAspectRatio="xMidYMid meet" fill="#8995FF"><path d="M141.2 36.7l-18.3.3.8 9.8c.4 5.3.8 11.9.8 14.7v5h-41-41l.3 17.9.3 17.9 6.7-.7c15.2-1.4 101.5-1.8 146.2-.7l48 1.6c1.3.4 1.5-2 1.5-17.8V66.5l-38.3.4c-21 .2-39.8 0-41.8-.3l-3.5-.7.3-15c.3-12.8.1-14.9-1.2-14.7-.8.1-9.7.4-19.8.5zm-56.7 76.9c-12.8 5-16 6.7-15.8 8.1.1 1 2.2 7.3 4.7 14 5.8 15.3 12.4 38.4 16.6 57.8l3.5 15.3c.2.2 8.3-2.5 18.2-6l17.9-6.3-1.2-6c-3.5-16.8-24.8-83.6-26.7-83.4-.7.1-8.4 3-17.2 6.5zm93.6 10.1c-10.4 41.7-22.9 83.2-27.1 90.1l-1.9 3.1-17.3.3c-20 .3-91.3-.9-94.3-1.6-1.9-.5-2 0-2 18v18.6l5-.6c2.8-.3 51.8-.9 109-1.2l104-.7v-17.6-17.6l-8.5.7c-4.7.3-19.5.7-32.9.7-19.1.1-24.2-.2-23.8-1.2.3-.6 2.2-5 4.2-9.7 6.5-15.2 29.6-86.3 28.4-87.4-.4-.4-32.6-9.4-36.5-10.3-2-.4-2.4.7-6.3 16.4z" /></svg>
|
<svg width="64" height="64" viewBox="0 0 288 288" preserveAspectRatio="xMidYMid meet" fill="#8995FF"><path d="M141.2 36.7l-18.3.3.8 9.8c.4 5.3.8 11.9.8 14.7v5h-41-41l.3 17.9.3 17.9 6.7-.7c15.2-1.4 101.5-1.8 146.2-.7l48 1.6c1.3.4 1.5-2 1.5-17.8V66.5l-38.3.4c-21 .2-39.8 0-41.8-.3l-3.5-.7.3-15c.3-12.8.1-14.9-1.2-14.7-.8.1-9.7.4-19.8.5zm-56.7 76.9c-12.8 5-16 6.7-15.8 8.1.1 1 2.2 7.3 4.7 14 5.8 15.3 12.4 38.4 16.6 57.8l3.5 15.3c.2.2 8.3-2.5 18.2-6l17.9-6.3-1.2-6c-3.5-16.8-24.8-83.6-26.7-83.4-.7.1-8.4 3-17.2 6.5zm93.6 10.1c-10.4 41.7-22.9 83.2-27.1 90.1l-1.9 3.1-17.3.3c-20 .3-91.3-.9-94.3-1.6-1.9-.5-2 0-2 18v18.6l5-.6c2.8-.3 51.8-.9 109-1.2l104-.7v-17.6-17.6l-8.5.7c-4.7.3-19.5.7-32.9.7-19.1.1-24.2-.2-23.8-1.2.3-.6 2.2-5 4.2-9.7 6.5-15.2 29.6-86.3 28.4-87.4-.4-.4-32.6-9.4-36.5-10.3-2-.4-2.4.7-6.3 16.4z" /></svg>
|
||||||
<div tw="text-slate-900 ml-2 mt-1 font-semibold">
|
<div tw="text-slate-900 ml-2 mt-1 font-semibold">
|
||||||
Tachiyomi
|
Tachiyomi
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="dir" tw="flex items-center text-slate-600">
|
<div v-if="dir" tw="flex items-center text-slate-600">
|
||||||
<div v-if="dir" tw="text-4xl font-semibold mr-2" v-html="dir" />
|
<div v-if="dir" tw="text-4xl font-semibold mr-2" v-html="dir" />
|
||||||
<svg v-if="dir === 'FAQ'" width="48" height="48" viewBox="0 -960 960 960" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M120-55.5q-15.5 0-26.5-11T82.5-93q0-15.5 11-26.5t26.5-11h720q15.5 0 26.5 11t11 26.5q0 15.5-11 26.5t-26.5 11H120ZM207-170q-15.5 0-26.5-11t-11-26.5v-193q-32.5-54-50.75-114.25T100.5-639.5q0-59 15.25-117.5t36.75-116q7.5-20 24.5-32.25t38-12.25q26.5 0 44.75 18.5T276-854.5l-5.5 92q-3 48.5 11 93t41.75 78Q351-558 391-537.75t89 20.25q59.5 0 116.5 11.5T697-471.5q43.5 23 68.25 58.5T790-326v118.5q0 15.5-11 26.5t-26.5 11h-355v-32q0-35 24-60.25T480-287.5h120q15.5 0 26.5-11t11-26.5q0-15.5-11-26.5t-26.5-11H480q-66 0-111.75 47T322.5-202v32H207Zm273-392.5q-65.5 0-111.5-46t-46-111.5q0-65.5 46-111.5t111.5-46q65.5 0 111.5 46t46 111.5q0 65.5-46 111.5t-111.5 46Z" /></svg>
|
<svg v-if="dir === 'FAQ'" width="48" height="48" viewBox="0 -960 960 960" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M120-55.5q-15.5 0-26.5-11T82.5-93q0-15.5 11-26.5t26.5-11h720q15.5 0 26.5 11t11 26.5q0 15.5-11 26.5t-26.5 11H120ZM207-170q-15.5 0-26.5-11t-11-26.5v-193q-32.5-54-50.75-114.25T100.5-639.5q0-59 15.25-117.5t36.75-116q7.5-20 24.5-32.25t38-12.25q26.5 0 44.75 18.5T276-854.5l-5.5 92q-3 48.5 11 93t41.75 78Q351-558 391-537.75t89 20.25q59.5 0 116.5 11.5T697-471.5q43.5 23 68.25 58.5T790-326v118.5q0 15.5-11 26.5t-26.5 11h-355v-32q0-35 24-60.25T480-287.5h120q15.5 0 26.5-11t11-26.5q0-15.5-11-26.5t-26.5-11H480q-66 0-111.75 47T322.5-202v32H207Zm273-392.5q-65.5 0-111.5-46t-46-111.5q0-65.5 46-111.5t111.5-46q65.5 0 111.5 46t46 111.5q0 65.5-46 111.5t-111.5 46Z" /></svg>
|
||||||
<svg v-else-if="dir === 'Guide'" height="48" width="48" viewBox="0 -960 960 960" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M831-327.5V-558L516-386.5q-17 9-36 9t-36-9l-329.5-180q-10-5.5-14.5-14.25t-4.5-18.75q0-10 4.5-18.75t14.5-14.25l330-179.5q8.5-5 17.25-7t18.25-2q9.5 0 18.25 2t17.25 7l371 202q9 5 14.25 13.75T906-577v249.5q0 15.5-11 26.5t-26.5 11q-15.5 0-26.5-11t-11-26.5Zm-387 173-197-107q-18.5-10-28.75-27.75T208-328v-149.5L444-349q17 9 36 9t36-9l236-128.5V-328q0 21-10.25 38.75T713-261.5l-197 107q-8.5 5-17.5 7t-18.5 2q-9.5 0-18.5-2t-17.5-7Z" /></svg>
|
<svg v-else-if="dir === 'Guide'" height="48" width="48" viewBox="0 -960 960 960" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M831-327.5V-558L516-386.5q-17 9-36 9t-36-9l-329.5-180q-10-5.5-14.5-14.25t-4.5-18.75q0-10 4.5-18.75t14.5-14.25l330-179.5q8.5-5 17.25-7t18.25-2q9.5 0 18.25 2t17.25 7l371 202q9 5 14.25 13.75T906-577v249.5q0 15.5-11 26.5t-26.5 11q-15.5 0-26.5-11t-11-26.5Zm-387 173-197-107q-18.5-10-28.75-27.75T208-328v-149.5L444-349q17 9 36 9t36-9l236-128.5V-328q0 21-10.25 38.75T713-261.5l-197 107q-8.5 5-17.5 7t-18.5 2q-9.5 0-18.5-2t-17.5-7Z" /></svg>
|
||||||
<svg v-else-if="dir === 'News'" height="48" width="48" viewBox="0 -960 960 960" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M157.5-122.5q-31 0-53-22t-22-53v-614q0-6.5 5.5-9t10.5 2.5l35.5 35.5q5.5 5.5 13 5.25t13-5.75l40-40q5.5-5.5 13-5.75t13 5.25l41 41q5.5 5.5 13 5.5t13-5.5l41-41q5.5-5.5 13-5.25t13 5.75l40 40q5.5 5.5 13 5.75t13-5.25l41-41q5.5-5.5 13-5.5t13 5.5l41 41q5.5 5.5 13 5.25t13-5.75l40-40q5.5-5.5 13-5.75t13 5.25l41 41q5.5 5.5 13 5.5t13-5.5l41-41q5.5-5.5 13-5.25t13 5.75l40 40q5.5 5.5 13 5.75t13-5.25l35.5-35.5q5-5 10.5-2.5t5.5 9v614q0 31-22 53t-53 22h-645Zm0-75h285v-245h-285v245Zm360 0h285v-85h-285v85Zm0-160h285v-85h-285v85Zm-360-160h645v-125h-645v125Z" /></svg>
|
<svg v-else-if="dir === 'News'" height="48" width="48" viewBox="0 -960 960 960" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M157.5-122.5q-31 0-53-22t-22-53v-614q0-6.5 5.5-9t10.5 2.5l35.5 35.5q5.5 5.5 13 5.25t13-5.75l40-40q5.5-5.5 13-5.75t13 5.25l41 41q5.5 5.5 13 5.5t13-5.5l41-41q5.5-5.5 13-5.25t13 5.75l40 40q5.5 5.5 13 5.75t13-5.25l41-41q5.5-5.5 13-5.5t13 5.5l41 41q5.5 5.5 13 5.25t13-5.75l40-40q5.5-5.5 13-5.75t13 5.25l41 41q5.5 5.5 13 5.5t13-5.5l41-41q5.5-5.5 13-5.25t13 5.75l40 40q5.5 5.5 13 5.75t13-5.25l35.5-35.5q5-5 10.5-2.5t5.5 9v614q0 31-22 53t-53 22h-645Zm0-75h285v-245h-285v245Zm360 0h285v-85h-285v85Zm0-160h285v-85h-285v85Zm-360-160h645v-125h-645v125Z" /></svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div tw="w-full pr-56 flex flex-col items-start justify-end">
|
<div tw="w-full pr-56 flex flex-col items-start justify-end">
|
||||||
<div tw="text-6xl font-bold text-slate-900" v-html="title" />
|
<div tw="text-6xl font-bold text-slate-900" v-html="title" />
|
||||||
<div v-if="description" tw="mt-2 text-4xl text-slate-600" v-html="description" />
|
<div v-if="description" tw="mt-2 text-4xl text-slate-600" v-html="description" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div tw="shrink-0 h-2 w-full flex" style="background-color: #8995ff;" />
|
<div tw="shrink-0 h-2 w-full flex" style="background-color: #8995ff;" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref, toRefs } from "vue"
|
import { computed, onMounted, ref, toRefs } from 'vue'
|
||||||
import moment from "moment"
|
import moment from 'moment'
|
||||||
import { type AppRelease, data as release } from "../data/release.data"
|
import { type AppRelease, data as release } from '../data/release.data'
|
||||||
|
|
||||||
const props = defineProps<{ type: keyof AppRelease }>()
|
const props = defineProps<{ type: keyof AppRelease }>()
|
||||||
const { type } = toRefs(props)
|
const { type } = toRefs(props)
|
||||||
|
|
||||||
const momentInfo = computed(() => ({
|
const momentInfo = computed(() => ({
|
||||||
relative: moment(release[type.value].published_at).fromNow(),
|
relative: moment(release[type.value].published_at).fromNow(),
|
||||||
exact: moment(release[type.value].published_at).format("dddd, MMMM Do YYYY [at] HH:mm"),
|
exact: moment(release[type.value].published_at).format('dddd, MMMM Do YYYY [at] HH:mm'),
|
||||||
iso: release[type.value].published_at ?? undefined,
|
iso: release[type.value].published_at ?? undefined,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Mimic the <ClientOnly /> behavior to show custom text while rendering.
|
// Mimic the <ClientOnly /> behavior to show custom text while rendering.
|
||||||
const show = ref(false)
|
const show = ref(false)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
show.value = true
|
show.value = true
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<time v-if="show" :datetime="momentInfo.iso" :title="momentInfo.exact">
|
<time v-if="show" :datetime="momentInfo.iso" :title="momentInfo.exact">
|
||||||
{{ momentInfo.relative }}
|
{{ momentInfo.relative }}
|
||||||
</time>
|
</time>
|
||||||
<time v-else :datetime="momentInfo.iso">
|
<time v-else :datetime="momentInfo.iso">
|
||||||
{{ momentInfo.exact }}
|
{{ momentInfo.exact }}
|
||||||
</time>
|
</time>
|
||||||
</template>
|
</template>
|
||||||
|
@ -11,17 +11,17 @@ import { IconRssBox } from '@iconify-prerendered/vue-mdi'
|
|||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.rss {
|
.rss {
|
||||||
& > * {
|
& > * {
|
||||||
vertical-align: middle
|
vertical-align: middle
|
||||||
position: relative
|
position: relative
|
||||||
bottom: 1px
|
bottom: 1px
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
width: 1em
|
width: 1em
|
||||||
height: 1em
|
height: 1em
|
||||||
display: inline-block
|
display: inline-block
|
||||||
margin-right: 4px
|
margin-right: 4px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { defineLoader } from "vitepress"
|
import { defineLoader } from 'vitepress'
|
||||||
import { Octokit } from "@octokit/rest"
|
import { Octokit } from '@octokit/rest'
|
||||||
import type { GetResponseDataTypeFromEndpointMethod } from "@octokit/types"
|
import type { GetResponseDataTypeFromEndpointMethod } from '@octokit/types'
|
||||||
|
|
||||||
const octokit = new Octokit()
|
const octokit = new Octokit()
|
||||||
|
|
||||||
@ -10,13 +10,13 @@ declare const data: GitHubReleaseList
|
|||||||
export { data }
|
export { data }
|
||||||
|
|
||||||
export default defineLoader({
|
export default defineLoader({
|
||||||
async load(): Promise<GitHubReleaseList> {
|
async load(): Promise<GitHubReleaseList> {
|
||||||
const releases = await octokit.paginate(octokit.repos.listReleases, {
|
const releases = await octokit.paginate(octokit.repos.listReleases, {
|
||||||
owner: "tachiyomiorg",
|
owner: 'tachiyomiorg',
|
||||||
repo: "tachiyomi",
|
repo: 'tachiyomi',
|
||||||
per_page: 100,
|
per_page: 100,
|
||||||
})
|
})
|
||||||
|
|
||||||
return releases
|
return releases
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
import { createContentLoader } from "vitepress"
|
import { createContentLoader } from 'vitepress'
|
||||||
|
|
||||||
export interface News {
|
export interface News {
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
date: string
|
date: string
|
||||||
url: string
|
url: string
|
||||||
}
|
}
|
||||||
|
|
||||||
declare const data: News[]
|
declare const data: News[]
|
||||||
export { data }
|
export { data }
|
||||||
|
|
||||||
export default createContentLoader("news/*.md", {
|
export default createContentLoader('news/*.md', {
|
||||||
excerpt: true,
|
excerpt: true,
|
||||||
transform(articles) {
|
transform(articles) {
|
||||||
return articles
|
return articles
|
||||||
.filter(({ url }) => url !== "/news/")
|
.filter(({ url }) => url !== '/news/')
|
||||||
.map(
|
.map(
|
||||||
({ frontmatter, url }) =>
|
({ frontmatter, url }) =>
|
||||||
<News>{
|
<News>{
|
||||||
title: frontmatter.title,
|
title: frontmatter.title,
|
||||||
description: frontmatter.description,
|
description: frontmatter.description,
|
||||||
date: frontmatter.date,
|
date: frontmatter.date,
|
||||||
url,
|
url,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.sort((a, b) => b.date.localeCompare(a.date))
|
.sort((a, b) => b.date.localeCompare(a.date))
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
import { defineLoader } from "vitepress"
|
import { defineLoader } from 'vitepress'
|
||||||
import { Octokit } from "@octokit/rest"
|
import { Octokit } from '@octokit/rest'
|
||||||
import type { GetResponseDataTypeFromEndpointMethod } from "@octokit/types"
|
import type { GetResponseDataTypeFromEndpointMethod } from '@octokit/types'
|
||||||
|
|
||||||
const octokit = new Octokit()
|
const octokit = new Octokit()
|
||||||
|
|
||||||
type GitHubRelease = GetResponseDataTypeFromEndpointMethod<typeof octokit.repos.getLatestRelease>
|
type GitHubRelease = GetResponseDataTypeFromEndpointMethod<typeof octokit.repos.getLatestRelease>
|
||||||
|
|
||||||
export interface AppRelease {
|
export interface AppRelease {
|
||||||
stable: GitHubRelease
|
stable: GitHubRelease
|
||||||
preview: GitHubRelease
|
preview: GitHubRelease
|
||||||
}
|
}
|
||||||
|
|
||||||
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 octokit.repos.getLatestRelease({
|
const { data: stable } = await octokit.repos.getLatestRelease({
|
||||||
owner: "tachiyomiorg",
|
owner: 'tachiyomiorg',
|
||||||
repo: "tachiyomi",
|
repo: 'tachiyomi',
|
||||||
})
|
})
|
||||||
|
|
||||||
const { data: preview } = await octokit.repos.getLatestRelease({
|
const { data: preview } = await octokit.repos.getLatestRelease({
|
||||||
owner: "tachiyomiorg",
|
owner: 'tachiyomiorg',
|
||||||
repo: "tachiyomi-preview",
|
repo: 'tachiyomi-preview',
|
||||||
})
|
})
|
||||||
|
|
||||||
return { stable, preview }
|
return { stable, preview }
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
// https://vitepress.dev/guide/custom-theme
|
// https://vitepress.dev/guide/custom-theme
|
||||||
import DefaultTheme from "vitepress/theme"
|
import DefaultTheme from 'vitepress/theme'
|
||||||
|
|
||||||
// Import Stylus files
|
// Import Stylus files
|
||||||
import "./styles/base.styl"
|
import './styles/base.styl'
|
||||||
|
|
||||||
// Import Global plugins
|
// Import Global plugins
|
||||||
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'
|
||||||
|
|
||||||
import { enhanceAppWithTabs } from "vitepress-plugin-tabs/client"
|
import { enhanceAppWithTabs } from 'vitepress-plugin-tabs/client'
|
||||||
|
|
||||||
// Import icon components
|
// Import icon components
|
||||||
import { IconBugReport, IconDownload, IconNewspaperVariant } from "@iconify-prerendered/vue-mdi"
|
import { IconBugReport, IconDownload, IconNewspaperVariant } from '@iconify-prerendered/vue-mdi'
|
||||||
|
|
||||||
import analytics from "./plugin/analytics"
|
import analytics from './plugin/analytics'
|
||||||
import Layout from "./Layout.vue"
|
import Layout from './Layout.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
extends: DefaultTheme,
|
extends: DefaultTheme,
|
||||||
enhanceApp({ app }) {
|
enhanceApp({ app }) {
|
||||||
app.use(VueQueryPlugin)
|
app.use(VueQueryPlugin)
|
||||||
enhanceAppWithTabs(app)
|
enhanceAppWithTabs(app)
|
||||||
app.component("IconDownload", IconDownload)
|
app.component('IconDownload', IconDownload)
|
||||||
app.component("IconNewspaperVariant", IconNewspaperVariant)
|
app.component('IconNewspaperVariant', IconNewspaperVariant)
|
||||||
app.component("IconBugReport", IconBugReport)
|
app.component('IconBugReport', IconBugReport)
|
||||||
analytics({ id: "G-2CBXXM1Y86" })
|
analytics({ id: 'G-2CBXXM1Y86' })
|
||||||
},
|
},
|
||||||
Layout,
|
Layout,
|
||||||
}
|
}
|
||||||
|
@ -3,35 +3,33 @@
|
|||||||
// https://github.com/ZhongxuYang/vitepress-plugin-google-analytics
|
// https://github.com/ZhongxuYang/vitepress-plugin-google-analytics
|
||||||
|
|
||||||
function mountGoogleAnalytics(id: string) {
|
function mountGoogleAnalytics(id: string) {
|
||||||
if (("dataLayer" in window && window.gtag) || window.location.hostname === "localhost") {
|
if (('dataLayer' in window && window.gtag) || window.location.hostname === 'localhost')
|
||||||
return
|
return
|
||||||
}
|
|
||||||
|
|
||||||
const analyticsScript = document.createElement("script")
|
const analyticsScript = document.createElement('script')
|
||||||
|
|
||||||
analyticsScript.addEventListener("load", () => {
|
analyticsScript.addEventListener('load', () => {
|
||||||
// @ts-expect-error Missing types
|
// @ts-expect-error Missing types
|
||||||
window.dataLayer = window.dataLayer || []
|
window.dataLayer = window.dataLayer || []
|
||||||
function gtag(..._args: any[]) {
|
function gtag(..._args: any[]) {
|
||||||
// @ts-expect-error Missing types
|
// @ts-expect-error Missing types
|
||||||
// eslint-disable-next-line prefer-rest-params
|
// eslint-disable-next-line prefer-rest-params
|
||||||
window.dataLayer.push(arguments)
|
window.dataLayer.push(arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
gtag("js", new Date())
|
gtag('js', new Date())
|
||||||
gtag("config", id)
|
gtag('config', id)
|
||||||
|
|
||||||
window.gtag = gtag
|
window.gtag = gtag
|
||||||
})
|
})
|
||||||
|
|
||||||
analyticsScript.src = `https://www.googletagmanager.com/gtag/js?id=${id}`
|
analyticsScript.src = `https://www.googletagmanager.com/gtag/js?id=${id}`
|
||||||
|
|
||||||
document.body.appendChild(analyticsScript)
|
document.body.appendChild(analyticsScript)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ({ id }: { id: string }) {
|
export default function ({ id }: { id: string }) {
|
||||||
// eslint-disable-next-line n/prefer-global/process
|
// eslint-disable-next-line node/prefer-global/process
|
||||||
if (process.env.NODE_ENV === "production" && id && typeof window !== "undefined") {
|
if (process.env.NODE_ENV === 'production' && id && typeof window !== 'undefined')
|
||||||
mountGoogleAnalytics(id)
|
mountGoogleAnalytics(id)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,44 +1,44 @@
|
|||||||
import type { UseQueryOptions } from "@tanstack/vue-query"
|
import type { UseQueryOptions } from '@tanstack/vue-query'
|
||||||
import { useQuery } from "@tanstack/vue-query"
|
import { 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'
|
||||||
|
|
||||||
export type ReleaseType = "stable" | "preview"
|
export type ReleaseType = 'stable' | 'preview'
|
||||||
|
|
||||||
export interface Extension {
|
export interface Extension {
|
||||||
name: string
|
name: string
|
||||||
pkg: string
|
pkg: string
|
||||||
apk: string
|
apk: string
|
||||||
lang: string
|
lang: string
|
||||||
code: number
|
code: number
|
||||||
version: string
|
version: string
|
||||||
nsfw: number
|
nsfw: number
|
||||||
hasReadme: number
|
hasReadme: number
|
||||||
hasChangelog: number
|
hasChangelog: number
|
||||||
sources: Source[]
|
sources: Source[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Source {
|
export interface Source {
|
||||||
name: string
|
name: string
|
||||||
lang: string
|
lang: string
|
||||||
id: string
|
id: string
|
||||||
baseUrl: string
|
baseUrl: string
|
||||||
versionId: number
|
versionId: number
|
||||||
}
|
}
|
||||||
|
|
||||||
type UseExtensionsRepositoryQueryOptions<S = Extension[]> =
|
type UseExtensionsRepositoryQueryOptions<S = Extension[]> =
|
||||||
UseQueryOptions<Extension[], Error, S>
|
UseQueryOptions<Extension[], Error, S>
|
||||||
|
|
||||||
export default function useExtensionsRepositoryQuery<S = Extension[]>(options: UseExtensionsRepositoryQueryOptions<S> = {}) {
|
export default function useExtensionsRepositoryQuery<S = Extension[]>(options: UseExtensionsRepositoryQueryOptions<S> = {}) {
|
||||||
return useQuery<Extension[], Error, S>({
|
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)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
initialData: () => [],
|
initialData: () => [],
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
...options,
|
...options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,14 @@
|
|||||||
$themeColor = #818cf8
|
$themeColor = #818cf8
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--vp-c-brand: $themeColor
|
--vp-c-brand: $themeColor
|
||||||
--vp-c-brand-light: tint($themeColor, 20%)
|
--vp-c-brand-light: tint($themeColor, 20%)
|
||||||
--vp-c-brand-lighter: tint($themeColor, 40%)
|
--vp-c-brand-lighter: tint($themeColor, 40%)
|
||||||
--vp-c-brand-lightest: tint($themeColor, 60%)
|
--vp-c-brand-lightest: tint($themeColor, 60%)
|
||||||
--vp-c-brand-dark: shade($themeColor, 25%)
|
--vp-c-brand-dark: shade($themeColor, 25%)
|
||||||
--vp-c-brand-darker: shade($themeColor, 50%)
|
--vp-c-brand-darker: shade($themeColor, 50%)
|
||||||
--vp-c-brand-darkest: shade($themeColor, 75%)
|
--vp-c-brand-darkest: shade($themeColor, 75%)
|
||||||
--vp-c-brand-dimm: alpha($themeColor, 0.08)
|
--vp-c-brand-dimm: alpha($themeColor, 0.08)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,23 +25,23 @@ $themeColor = #818cf8
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
html:not(.dark) {
|
html:not(.dark) {
|
||||||
img[data-mode="darkmode-only"] {
|
img[data-mode="darkmode-only"] {
|
||||||
display: none !important
|
display: none !important
|
||||||
|
|
||||||
& + figcaption {
|
& + figcaption {
|
||||||
display: none !important
|
display: none !important
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
img[data-mode="lightmode-only"] {
|
img[data-mode="lightmode-only"] {
|
||||||
display: none !important
|
display: none !important
|
||||||
|
|
||||||
& + figcaption {
|
& + figcaption {
|
||||||
display: none !important
|
display: none !important
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,7 +49,7 @@ html:not(.dark) {
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--vp-button-brand-bg: var(--vp-c-brand-darker)
|
--vp-button-brand-bg: var(--vp-c-brand-darker)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,32 +57,32 @@ html:not(.dark) {
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--vp-home-hero-name-color: transparent
|
--vp-home-hero-name-color: transparent
|
||||||
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand) 30%, var(--vp-c-brand-dark))
|
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand) 30%, var(--vp-c-brand-dark))
|
||||||
--vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-light) 50%, var(--vp-c-brand-lighter) 50%)
|
--vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-light) 50%, var(--vp-c-brand-lighter) 50%)
|
||||||
--vp-home-hero-image-filter: blur(40px)
|
--vp-home-hero-image-filter: blur(40px)
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-darker) 25%, var(--vp-c-brand-darkest) 25%)
|
--vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-darker) 25%, var(--vp-c-brand-darkest) 25%)
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width 640px) {
|
@media (min-width 640px) {
|
||||||
:root {
|
:root {
|
||||||
--vp-home-hero-image-filter: blur(56px)
|
--vp-home-hero-image-filter: blur(56px)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width 960px) {
|
@media (min-width 960px) {
|
||||||
:root {
|
:root {
|
||||||
--vp-home-hero-image-filter: blur(72px)
|
--vp-home-hero-image-filter: blur(72px)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.VPFooter {
|
.VPFooter {
|
||||||
.divider {
|
.divider {
|
||||||
color: var(--vp-c-divider)
|
color: var(--vp-c-divider)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,22 +90,22 @@ html:not(.dark) {
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--vp-custom-block-tip-border: var(--vp-c-brand)
|
--vp-custom-block-tip-border: var(--vp-c-brand)
|
||||||
--vp-custom-block-tip-text: var(--vp-c-brand-darker)
|
--vp-custom-block-tip-text: var(--vp-c-brand-darker)
|
||||||
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm)
|
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm)
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--vp-custom-block-tip-border: var(--vp-c-brand)
|
--vp-custom-block-tip-border: var(--vp-c-brand)
|
||||||
--vp-custom-block-tip-text: var(--vp-c-brand-lightest)
|
--vp-custom-block-tip-text: var(--vp-c-brand-lightest)
|
||||||
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm)
|
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm)
|
||||||
--vp-custom-block-info-bg: #212127
|
--vp-custom-block-info-bg: #212127
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-tabs {
|
.plugin-tabs {
|
||||||
&--content {
|
&--content {
|
||||||
padding: 2rem !important
|
padding: 2rem !important
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,11 +113,11 @@ html:not(.dark) {
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
.DocSearch {
|
.DocSearch {
|
||||||
--docsearch-primary-color: var(--vp-c-brand) !important
|
--docsearch-primary-color: var(--vp-c-brand) !important
|
||||||
}
|
}
|
||||||
|
|
||||||
.VPImage.image-src {
|
.VPImage.image-src {
|
||||||
border-radius: 8px
|
border-radius: 8px
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,12 +125,12 @@ html:not(.dark) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.VPLocalSearchBox {
|
.VPLocalSearchBox {
|
||||||
--vp-local-search-highlight-bg: var(--vp-c-brand-soft)
|
--vp-local-search-highlight-bg: var(--vp-c-brand-soft)
|
||||||
--vp-local-search-highlight-text: var(--vp-c-brand-dark)
|
--vp-local-search-highlight-text: var(--vp-c-brand-dark)
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .VPLocalSearchBox {
|
.dark .VPLocalSearchBox {
|
||||||
--vp-local-search-highlight-text: var(--vp-c-brand-lightest)
|
--vp-local-search-highlight-text: var(--vp-c-brand-lightest)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,39 +140,39 @@ html:not(.dark) {
|
|||||||
// Shitty method to give elevation to image - TO BE REPLACED
|
// Shitty method to give elevation to image - TO BE REPLACED
|
||||||
|
|
||||||
main figure {
|
main figure {
|
||||||
margin: 2rem 0
|
margin: 2rem 0
|
||||||
transition: transform var(--vp-tt)
|
transition: transform var(--vp-tt)
|
||||||
|
|
||||||
img {
|
img {
|
||||||
margin: 0 auto
|
margin: 0 auto
|
||||||
border-radius: 12px
|
border-radius: 12px
|
||||||
box-shadow: 2px 2px 8px 4px var(--vp-c-bg-alt)
|
box-shadow: 2px 2px 8px 4px var(--vp-c-bg-alt)
|
||||||
}
|
}
|
||||||
|
|
||||||
figcaption {
|
figcaption {
|
||||||
text-align: center
|
text-align: center
|
||||||
margin-top: 1.25rem
|
margin-top: 1.25rem
|
||||||
font-size: 0.875rem
|
font-size: 0.875rem
|
||||||
color: var(--vp-c-text-2)
|
color: var(--vp-c-text-2)
|
||||||
}
|
}
|
||||||
|
|
||||||
& > a .external-link-icon {
|
& > a .external-link-icon {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main :where(h1, h2, h3, h4, h5, h6) + figure {
|
main :where(h1, h2, h3, h4, h5, h6) + figure {
|
||||||
margin-top: 1.5rem
|
margin-top: 1.5rem
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-block {
|
.custom-block {
|
||||||
figure figcaption {
|
figure figcaption {
|
||||||
color: inherit
|
color: inherit
|
||||||
}
|
}
|
||||||
|
|
||||||
&.tip figure img {
|
&.tip figure img {
|
||||||
--vp-c-bg-alt: var(--vp-custom-block-tip-bg)
|
--vp-c-bg-alt: var(--vp-custom-block-tip-bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -180,19 +180,19 @@ main :where(h1, h2, h3, h4, h5, h6) + figure {
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
figure:has(img)>a[href^="http://"]:after,
|
figure:has(img)>a[href^="http://"]:after,
|
||||||
figure:has(img)>a[href^="https://"]:after {
|
figure:has(img)>a[href^="https://"]:after {
|
||||||
content: ""
|
content: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vp-doc a {
|
.vp-doc a {
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: underline
|
text-decoration: underline
|
||||||
text-underline-offset: 2px
|
text-underline-offset: 2px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -200,28 +200,28 @@ main :where(h1, h2, h3, h4, h5, h6) + figure {
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
.navigation {
|
.navigation {
|
||||||
color: var(--vp-c-green-2)
|
color: var(--vp-c-green-2)
|
||||||
font-weight: 600
|
font-weight: 600
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--vp-c-green-1)
|
color: var(--vp-c-green-1)
|
||||||
cursor: default
|
cursor: default
|
||||||
}
|
}
|
||||||
|
|
||||||
svg,
|
svg,
|
||||||
span.name {
|
span.name {
|
||||||
vertical-align: middle // Align both SVG and <span> vertically
|
vertical-align: middle // Align both SVG and <span> vertically
|
||||||
position: relative
|
position: relative
|
||||||
bottom: 1px
|
bottom: 1px
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
fill: currentColor
|
fill: currentColor
|
||||||
height: 1em
|
height: 1em
|
||||||
width: 1em
|
width: 1em
|
||||||
display: inline-block
|
display: inline-block
|
||||||
margin-right: 4px
|
margin-right: 4px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -229,7 +229,7 @@ main :where(h1, h2, h3, h4, h5, h6) + figure {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
body {
|
body {
|
||||||
--el-color-primary: var(--vp-c-brand-1)
|
--el-color-primary: var(--vp-c-brand-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -237,15 +237,15 @@ body {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.menu + .appearance::before {
|
.menu + .appearance::before {
|
||||||
margin-right: 8px !important
|
margin-right: 8px !important
|
||||||
}
|
}
|
||||||
|
|
||||||
.appearance + .social-links::before {
|
.appearance + .social-links::before {
|
||||||
margin-left: 8px !important
|
margin-left: 8px !important
|
||||||
}
|
}
|
||||||
|
|
||||||
.VPMenu .CustomSwitchAppearance {
|
.VPMenu .CustomSwitchAppearance {
|
||||||
margin-right: -8px
|
margin-right: -8px
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -253,26 +253,26 @@ body {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.forks .VPFeatures {
|
.forks .VPFeatures {
|
||||||
padding: 2rem 0 !important
|
padding: 2rem 0 !important
|
||||||
|
|
||||||
.VPLink:hover {
|
.VPLink:hover {
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
line-height: 24px
|
line-height: 24px
|
||||||
font-size: 16px
|
font-size: 16px
|
||||||
font-weight: 600
|
font-weight: 600
|
||||||
margin: 0
|
margin: 0
|
||||||
border-top: none
|
border-top: none
|
||||||
padding-top: 0
|
padding-top: 0
|
||||||
letter-spacing: 0
|
letter-spacing: 0
|
||||||
color: var(--vp-c-text-1)
|
color: var(--vp-c-text-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width 640px) {
|
@media (min-width 640px) {
|
||||||
.forks .item.grid-4 {
|
.forks .item.grid-4 {
|
||||||
width: 50% !important
|
width: 50% !important
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
.extension-list {
|
.extension-list {
|
||||||
> div {
|
> div {
|
||||||
&:not(:first-of-type) {
|
&:not(:first-of-type) {
|
||||||
.extensions-total {
|
.extensions-total {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,29 +2,29 @@
|
|||||||
$themeColor = #ff6884
|
$themeColor = #ff6884
|
||||||
|
|
||||||
.page-neko {
|
.page-neko {
|
||||||
.VPHero {
|
.VPHero {
|
||||||
h1 {
|
h1 {
|
||||||
.clip {
|
.clip {
|
||||||
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand) 30%, var(--vp-c-brand-dark))
|
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand) 30%, var(--vp-c-brand-dark))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.VPButton {
|
.VPButton {
|
||||||
&.brand {
|
&.brand {
|
||||||
border-color: var(--vp-button-brand-border)
|
border-color: var(--vp-button-brand-border)
|
||||||
color: var(--vp-button-brand-text)
|
color: var(--vp-button-brand-text)
|
||||||
background-color: var(--vp-button-brand-bg)
|
background-color: var(--vp-button-brand-bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-bg {
|
.image-bg {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
background: alpha($themeColor, 0.2)
|
background: alpha($themeColor, 0.2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -33,14 +33,14 @@ $themeColor = #ff6884
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root .page-neko {
|
:root .page-neko {
|
||||||
--vp-c-brand: $themeColor
|
--vp-c-brand: $themeColor
|
||||||
--vp-c-brand-light: tint($themeColor, 20%)
|
--vp-c-brand-light: tint($themeColor, 20%)
|
||||||
--vp-c-brand-lighter: tint($themeColor, 40%)
|
--vp-c-brand-lighter: tint($themeColor, 40%)
|
||||||
--vp-c-brand-lightest: tint($themeColor, 60%)
|
--vp-c-brand-lightest: tint($themeColor, 60%)
|
||||||
--vp-c-brand-dark: shade($themeColor, 25%)
|
--vp-c-brand-dark: shade($themeColor, 25%)
|
||||||
--vp-c-brand-darker: shade($themeColor, 50%)
|
--vp-c-brand-darker: shade($themeColor, 50%)
|
||||||
--vp-c-brand-darkest: shade($themeColor, 75%)
|
--vp-c-brand-darkest: shade($themeColor, 75%)
|
||||||
--vp-c-brand-dimm: alpha($themeColor, 0.08)
|
--vp-c-brand-dimm: alpha($themeColor, 0.08)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,13 +48,13 @@ $themeColor = #ff6884
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root .page-neko {
|
:root .page-neko {
|
||||||
--vp-button-brand-border: var(--vp-c-brand-light)
|
--vp-button-brand-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-text: var(--vp-c-black)
|
--vp-button-brand-text: var(--vp-c-black)
|
||||||
--vp-button-brand-bg: var(--vp-c-brand)
|
--vp-button-brand-bg: var(--vp-c-brand)
|
||||||
--vp-button-brand-hover-border: var(--vp-c-brand-light)
|
--vp-button-brand-hover-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-hover-text: var(--vp-c-black)
|
--vp-button-brand-hover-text: var(--vp-c-black)
|
||||||
--vp-button-brand-hover-bg: var(--vp-c-brand-light)
|
--vp-button-brand-hover-bg: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-active-border: var(--vp-c-brand-light)
|
--vp-button-brand-active-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-active-text: var(--vp-c-black)
|
--vp-button-brand-active-text: var(--vp-c-black)
|
||||||
--vp-button-brand-active-bg: var(--vp-button-brand-bg)
|
--vp-button-brand-active-bg: var(--vp-button-brand-bg)
|
||||||
}
|
}
|
||||||
|
@ -2,29 +2,29 @@
|
|||||||
$themeColor = #ffcc4d
|
$themeColor = #ffcc4d
|
||||||
|
|
||||||
.page-tachiyomi-az {
|
.page-tachiyomi-az {
|
||||||
.VPHero {
|
.VPHero {
|
||||||
h1 {
|
h1 {
|
||||||
.clip {
|
.clip {
|
||||||
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand) 30%, var(--vp-c-brand-dark))
|
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand) 30%, var(--vp-c-brand-dark))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.VPButton {
|
.VPButton {
|
||||||
&.brand {
|
&.brand {
|
||||||
border-color: var(--vp-button-brand-border)
|
border-color: var(--vp-button-brand-border)
|
||||||
color: var(--vp-button-brand-text)
|
color: var(--vp-button-brand-text)
|
||||||
background-color: var(--vp-button-brand-bg)
|
background-color: var(--vp-button-brand-bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-bg {
|
.image-bg {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
background: alpha($themeColor, 0.2)
|
background: alpha($themeColor, 0.2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -33,14 +33,14 @@ $themeColor = #ffcc4d
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root .page-tachiyomi-az {
|
:root .page-tachiyomi-az {
|
||||||
--vp-c-brand: $themeColor
|
--vp-c-brand: $themeColor
|
||||||
--vp-c-brand-light: tint($themeColor, 20%)
|
--vp-c-brand-light: tint($themeColor, 20%)
|
||||||
--vp-c-brand-lighter: tint($themeColor, 40%)
|
--vp-c-brand-lighter: tint($themeColor, 40%)
|
||||||
--vp-c-brand-lightest: tint($themeColor, 60%)
|
--vp-c-brand-lightest: tint($themeColor, 60%)
|
||||||
--vp-c-brand-dark: shade($themeColor, 25%)
|
--vp-c-brand-dark: shade($themeColor, 25%)
|
||||||
--vp-c-brand-darker: shade($themeColor, 50%)
|
--vp-c-brand-darker: shade($themeColor, 50%)
|
||||||
--vp-c-brand-darkest: shade($themeColor, 75%)
|
--vp-c-brand-darkest: shade($themeColor, 75%)
|
||||||
--vp-c-brand-dimm: alpha($themeColor, 0.08)
|
--vp-c-brand-dimm: alpha($themeColor, 0.08)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,156 +48,156 @@ $themeColor = #ffcc4d
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root .page-tachiyomi-az {
|
:root .page-tachiyomi-az {
|
||||||
--vp-button-brand-border: var(--vp-c-brand-light)
|
--vp-button-brand-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-text: var(--vp-c-black)
|
--vp-button-brand-text: var(--vp-c-black)
|
||||||
--vp-button-brand-bg: var(--vp-c-brand)
|
--vp-button-brand-bg: var(--vp-c-brand)
|
||||||
--vp-button-brand-hover-border: var(--vp-c-brand-light)
|
--vp-button-brand-hover-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-hover-text: var(--vp-c-black)
|
--vp-button-brand-hover-text: var(--vp-c-black)
|
||||||
--vp-button-brand-hover-bg: var(--vp-c-brand-light)
|
--vp-button-brand-hover-bg: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-active-border: var(--vp-c-brand-light)
|
--vp-button-brand-active-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-active-text: var(--vp-c-black)
|
--vp-button-brand-active-text: var(--vp-c-black)
|
||||||
--vp-button-brand-active-bg: var(--vp-button-brand-bg)
|
--vp-button-brand-active-bg: var(--vp-button-brand-bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component: Dumb
|
* Component: Dumb
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Comic Sans MS'
|
font-family: 'Comic Sans MS'
|
||||||
src: url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.eot')
|
src: url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.eot')
|
||||||
src: url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.eot?#iefix') format('embedded-opentype'), url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.woff2') format('woff2'), url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.woff') format('woff'), url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.ttf') format('truetype'), url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.svg#Comic Sans MS') format('svg')
|
src: url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.eot?#iefix') format('embedded-opentype'), url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.woff2') format('woff2'), url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.woff') format('woff'), url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.ttf') format('truetype'), url('//db.onlinewebfonts.com/t/7cc6719bd5f0310be3150ba33418e72e.svg#Comic Sans MS') format('svg')
|
||||||
}
|
}
|
||||||
|
|
||||||
.azContainer {
|
.azContainer {
|
||||||
width: 100%
|
width: 100%
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
|
|
||||||
.azMarquee {
|
.azMarquee {
|
||||||
display: inline-block
|
display: inline-block
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
white-space: nowrap
|
white-space: nowrap
|
||||||
animation: marquee 10s linear infinite
|
animation: marquee 10s linear infinite
|
||||||
padding-left: 100%
|
padding-left: 100%
|
||||||
|
|
||||||
.azWiggleText {
|
.azWiggleText {
|
||||||
padding: 2em
|
padding: 2em
|
||||||
width: fit-content
|
width: fit-content
|
||||||
animation: wiggleAnimation 1s ease-out infinite
|
animation: wiggleAnimation 1s ease-out infinite
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
animation: barrelRollAnimation 0.6s
|
animation: barrelRollAnimation 0.6s
|
||||||
}
|
}
|
||||||
|
|
||||||
.azText {
|
.azText {
|
||||||
font-family: 'Comic Sans MS', 'Comic Sans', cursive
|
font-family: 'Comic Sans MS', 'Comic Sans', cursive
|
||||||
font-size: 2em
|
font-size: 2em
|
||||||
display: inline-block
|
display: inline-block
|
||||||
-webkit-text-stroke: 1px black
|
-webkit-text-stroke: 1px black
|
||||||
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000
|
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000
|
||||||
animation: rainbowTextColorAnimation 0.5s linear infinite, scaleXTextAnimation 2s infinite
|
animation: rainbowTextColorAnimation 0.5s linear infinite, scaleXTextAnimation 2s infinite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes marquee {
|
@keyframes marquee {
|
||||||
0% {
|
0% {
|
||||||
transform: translate(0, 0)
|
transform: translate(0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: translate(-100%, 0)
|
transform: translate(-100%, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes barrelRollAnimation {
|
@keyframes barrelRollAnimation {
|
||||||
from {
|
from {
|
||||||
transform: rotate(0)
|
transform: rotate(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
transform: rotate(360deg)
|
transform: rotate(360deg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes wiggleAnimation {
|
@keyframes wiggleAnimation {
|
||||||
0% {
|
0% {
|
||||||
transform: rotate(0)
|
transform: rotate(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
25% {
|
25% {
|
||||||
transform: rotate(-15deg)
|
transform: rotate(-15deg)
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
transform: rotate(0)
|
transform: rotate(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
75% {
|
75% {
|
||||||
transform: rotate(15deg)
|
transform: rotate(15deg)
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: rotate(0)
|
transform: rotate(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes scaleXTextAnimation {
|
@keyframes scaleXTextAnimation {
|
||||||
0% {
|
0% {
|
||||||
transform: scaleX(0.5) scaleY(0.5)
|
transform: scaleX(0.5) scaleY(0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
transform: scaleX(1) scaleY(1)
|
transform: scaleX(1) scaleY(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: scaleX(0.5) scaleY(0.5)
|
transform: scaleX(0.5) scaleY(0.5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes rainbowTextColorAnimation {
|
@keyframes rainbowTextColorAnimation {
|
||||||
0% {
|
0% {
|
||||||
color: hsl(0, 100%, 50%)
|
color: hsl(0, 100%, 50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
10% {
|
10% {
|
||||||
color: hsl(36, 100%, 50%)
|
color: hsl(36, 100%, 50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
20% {
|
20% {
|
||||||
color: hsl(72, 100%, 50%)
|
color: hsl(72, 100%, 50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
30% {
|
30% {
|
||||||
color: hsl(108, 100%, 50%)
|
color: hsl(108, 100%, 50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
40% {
|
40% {
|
||||||
color: hsl(144, 100%, 50%)
|
color: hsl(144, 100%, 50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
color: hsl(180, 100%, 50%)
|
color: hsl(180, 100%, 50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
60% {
|
60% {
|
||||||
color: hsl(216, 100%, 50%)
|
color: hsl(216, 100%, 50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
70% {
|
70% {
|
||||||
color: hsl(252, 100%, 50%)
|
color: hsl(252, 100%, 50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
80% {
|
80% {
|
||||||
color: hsl(288, 100%, 50%)
|
color: hsl(288, 100%, 50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
90% {
|
90% {
|
||||||
color: hsl(324, 100%, 50%)
|
color: hsl(324, 100%, 50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
color: hsl(360, 100%, 50%)
|
color: hsl(360, 100%, 50%)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,29 +2,29 @@
|
|||||||
$themeColor = #0952af
|
$themeColor = #0952af
|
||||||
|
|
||||||
.page-tachiyomi-j2k {
|
.page-tachiyomi-j2k {
|
||||||
.VPHero {
|
.VPHero {
|
||||||
h1 {
|
h1 {
|
||||||
.clip {
|
.clip {
|
||||||
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand) 30%, var(--vp-c-brand-dark))
|
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand) 30%, var(--vp-c-brand-dark))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.VPButton {
|
.VPButton {
|
||||||
&.brand {
|
&.brand {
|
||||||
border-color: var(--vp-button-brand-border)
|
border-color: var(--vp-button-brand-border)
|
||||||
color: var(--vp-button-brand-text)
|
color: var(--vp-button-brand-text)
|
||||||
background-color: var(--vp-button-brand-bg)
|
background-color: var(--vp-button-brand-bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-bg {
|
.image-bg {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
background: alpha($themeColor, 0.2)
|
background: alpha($themeColor, 0.2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -33,14 +33,14 @@ $themeColor = #0952af
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root .page-tachiyomi-j2k {
|
:root .page-tachiyomi-j2k {
|
||||||
--vp-c-brand: $themeColor
|
--vp-c-brand: $themeColor
|
||||||
--vp-c-brand-light: tint($themeColor, 20%)
|
--vp-c-brand-light: tint($themeColor, 20%)
|
||||||
--vp-c-brand-lighter: tint($themeColor, 40%)
|
--vp-c-brand-lighter: tint($themeColor, 40%)
|
||||||
--vp-c-brand-lightest: tint($themeColor, 60%)
|
--vp-c-brand-lightest: tint($themeColor, 60%)
|
||||||
--vp-c-brand-dark: shade($themeColor, 25%)
|
--vp-c-brand-dark: shade($themeColor, 25%)
|
||||||
--vp-c-brand-darker: shade($themeColor, 50%)
|
--vp-c-brand-darker: shade($themeColor, 50%)
|
||||||
--vp-c-brand-darkest: shade($themeColor, 75%)
|
--vp-c-brand-darkest: shade($themeColor, 75%)
|
||||||
--vp-c-brand-dimm: alpha($themeColor, 0.08)
|
--vp-c-brand-dimm: alpha($themeColor, 0.08)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,13 +48,13 @@ $themeColor = #0952af
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root .page-tachiyomi-j2k {
|
:root .page-tachiyomi-j2k {
|
||||||
--vp-button-brand-border: var(--vp-c-brand-light)
|
--vp-button-brand-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-text: var(--vp-c-white)
|
--vp-button-brand-text: var(--vp-c-white)
|
||||||
--vp-button-brand-bg: var(--vp-c-brand)
|
--vp-button-brand-bg: var(--vp-c-brand)
|
||||||
--vp-button-brand-hover-border: var(--vp-c-brand-light)
|
--vp-button-brand-hover-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-hover-text: var(--vp-c-white)
|
--vp-button-brand-hover-text: var(--vp-c-white)
|
||||||
--vp-button-brand-hover-bg: var(--vp-c-brand-light)
|
--vp-button-brand-hover-bg: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-active-border: var(--vp-c-brand-light)
|
--vp-button-brand-active-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-active-text: var(--vp-c-white)
|
--vp-button-brand-active-text: var(--vp-c-white)
|
||||||
--vp-button-brand-active-bg: var(--vp-button-brand-bg)
|
--vp-button-brand-active-bg: var(--vp-button-brand-bg)
|
||||||
}
|
}
|
||||||
|
@ -2,29 +2,29 @@
|
|||||||
$themeColor = #ce2828
|
$themeColor = #ce2828
|
||||||
|
|
||||||
.page-tachiyomi-sy {
|
.page-tachiyomi-sy {
|
||||||
.VPHero {
|
.VPHero {
|
||||||
h1 {
|
h1 {
|
||||||
.clip {
|
.clip {
|
||||||
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand) 30%, var(--vp-c-brand-dark))
|
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand) 30%, var(--vp-c-brand-dark))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.VPButton {
|
.VPButton {
|
||||||
&.brand {
|
&.brand {
|
||||||
border-color: var(--vp-button-brand-border)
|
border-color: var(--vp-button-brand-border)
|
||||||
color: var(--vp-button-brand-text)
|
color: var(--vp-button-brand-text)
|
||||||
background-color: var(--vp-button-brand-bg)
|
background-color: var(--vp-button-brand-bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-bg {
|
.image-bg {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
background: alpha($themeColor, 0.2)
|
background: alpha($themeColor, 0.2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -33,14 +33,14 @@ $themeColor = #ce2828
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root .page-tachiyomi-sy {
|
:root .page-tachiyomi-sy {
|
||||||
--vp-c-brand: $themeColor
|
--vp-c-brand: $themeColor
|
||||||
--vp-c-brand-light: tint($themeColor, 20%)
|
--vp-c-brand-light: tint($themeColor, 20%)
|
||||||
--vp-c-brand-lighter: tint($themeColor, 40%)
|
--vp-c-brand-lighter: tint($themeColor, 40%)
|
||||||
--vp-c-brand-lightest: tint($themeColor, 60%)
|
--vp-c-brand-lightest: tint($themeColor, 60%)
|
||||||
--vp-c-brand-dark: shade($themeColor, 25%)
|
--vp-c-brand-dark: shade($themeColor, 25%)
|
||||||
--vp-c-brand-darker: shade($themeColor, 50%)
|
--vp-c-brand-darker: shade($themeColor, 50%)
|
||||||
--vp-c-brand-darkest: shade($themeColor, 75%)
|
--vp-c-brand-darkest: shade($themeColor, 75%)
|
||||||
--vp-c-brand-dimm: alpha($themeColor, 0.08)
|
--vp-c-brand-dimm: alpha($themeColor, 0.08)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,13 +48,13 @@ $themeColor = #ce2828
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
:root .page-tachiyomi-sy {
|
:root .page-tachiyomi-sy {
|
||||||
--vp-button-brand-border: var(--vp-c-brand-light)
|
--vp-button-brand-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-text: var(--vp-c-white)
|
--vp-button-brand-text: var(--vp-c-white)
|
||||||
--vp-button-brand-bg: var(--vp-c-brand)
|
--vp-button-brand-bg: var(--vp-c-brand)
|
||||||
--vp-button-brand-hover-border: var(--vp-c-brand-light)
|
--vp-button-brand-hover-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-hover-text: var(--vp-c-white)
|
--vp-button-brand-hover-text: var(--vp-c-white)
|
||||||
--vp-button-brand-hover-bg: var(--vp-c-brand-light)
|
--vp-button-brand-hover-bg: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-active-border: var(--vp-c-brand-light)
|
--vp-button-brand-active-border: var(--vp-c-brand-light)
|
||||||
--vp-button-brand-active-text: var(--vp-c-white)
|
--vp-button-brand-active-text: var(--vp-c-white)
|
||||||
--vp-button-brand-active-bg: var(--vp-button-brand-bg)
|
--vp-button-brand-active-bg: var(--vp-button-brand-bg)
|
||||||
}
|
}
|
||||||
|
@ -1,99 +1,99 @@
|
|||||||
.tree {
|
.tree {
|
||||||
border-radius: 8px
|
border-radius: 8px
|
||||||
margin: 16px
|
margin: 16px
|
||||||
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: var(--vp-font-family-mono)
|
font-family: var(--vp-font-family-mono)
|
||||||
font-size: 0.85rem
|
font-size: 0.85rem
|
||||||
line-height: 1.5
|
line-height: 1.5
|
||||||
|
|
||||||
& > ul {
|
& > ul {
|
||||||
margin: 0
|
margin: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
& + li {
|
& + li {
|
||||||
margin-top: 0
|
margin-top: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
&.folder {
|
&.folder {
|
||||||
&.root,
|
&.root,
|
||||||
&.main {
|
&.main {
|
||||||
color: var(--vp-c-brand-darker)
|
color: var(--vp-c-brand-darker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.file.zip {
|
&.file.zip {
|
||||||
color: var(--vp-c-brand-darker) !important
|
color: var(--vp-c-brand-darker) !important
|
||||||
}
|
}
|
||||||
|
|
||||||
&.file {
|
&.file {
|
||||||
.file-extension {
|
.file-extension {
|
||||||
color: var(--vp-c-text-2)
|
color: var(--vp-c-text-2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
padding-left: 5px
|
padding-left: 5px
|
||||||
list-style: none
|
list-style: none
|
||||||
|
|
||||||
li {
|
li {
|
||||||
position: relative
|
position: relative
|
||||||
padding-left: 15px
|
padding-left: 15px
|
||||||
-webkit-box-sizing: border-box
|
-webkit-box-sizing: border-box
|
||||||
-moz-box-sizing: border-box
|
-moz-box-sizing: border-box
|
||||||
box-sizing: border-box
|
box-sizing: border-box
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
top: 15px
|
top: 15px
|
||||||
left: 0
|
left: 0
|
||||||
width: 10px
|
width: 10px
|
||||||
height: 1px
|
height: 1px
|
||||||
margin: auto
|
margin: auto
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
top: 0
|
top: 0
|
||||||
bottom: 0
|
bottom: 0
|
||||||
left: 0
|
left: 0
|
||||||
width: 1px
|
width: 1px
|
||||||
height: 100%
|
height: 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before,
|
&:before,
|
||||||
&:after {
|
&:after {
|
||||||
position: absolute
|
position: absolute
|
||||||
content: ''
|
content: ''
|
||||||
background-color: var(--vp-c-text-3)
|
background-color: var(--vp-c-text-3)
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
&:after {
|
&:after {
|
||||||
height: 15px
|
height: 15px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-icon {
|
&-icon {
|
||||||
height: 12px
|
height: 12px
|
||||||
width: 12px
|
width: 12px
|
||||||
margin-right: 6px
|
margin-right: 6px
|
||||||
display: inline-block
|
display: inline-block
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
.tree {
|
.tree {
|
||||||
span {
|
span {
|
||||||
&.folder,
|
&.folder,
|
||||||
&.file.zip {
|
&.file.zip {
|
||||||
color: var(--vp-c-brand-lighter) !important
|
color: var(--vp-c-brand-lighter) !important
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
website/src/.vitepress/vue-shim.d.ts
vendored
4
website/src/.vitepress/vue-shim.d.ts
vendored
@ -1,5 +1,5 @@
|
|||||||
declare module "*.vue" {
|
declare module '*.vue' {
|
||||||
import type { Component } from "vue"
|
import type { Component } from 'vue'
|
||||||
|
|
||||||
const _default: Component
|
const _default: Component
|
||||||
export default _default
|
export default _default
|
||||||
|
Loading…
Reference in New Issue
Block a user