components: add AMWDocsAsideMeta
This commit is contained in:
parent
091b8e9085
commit
fdec5d2991
@ -1,8 +1,8 @@
|
||||
import { defineConfig } from 'vitepress'
|
||||
import { defineConfigWithTheme } from 'vitepress'
|
||||
import { nav, sidebar } from './data/navigations'
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
export default defineConfigWithTheme({
|
||||
title: "ALT Mobile Wiki",
|
||||
titleTemplate: ':title — ALT Mobile Wiki',
|
||||
description: "официальная библиотека знаний операционной системы ALT Mobile",
|
||||
@ -37,6 +37,64 @@ export default defineConfig({
|
||||
title: 'Страница не найдена',
|
||||
quote: 'Похоже, что вы перешли по неверной или устаревшей ссылке. Вы можете воспользоваться поиском.',
|
||||
linkText: 'Вернуться на главную'
|
||||
},
|
||||
asideMeta: {
|
||||
developer: {
|
||||
label: 'Разрабочик'
|
||||
},
|
||||
keywords: {
|
||||
core: {
|
||||
name: 'GNOME Core',
|
||||
type: 'info'
|
||||
},
|
||||
circle: {
|
||||
name: 'GNOME Circle',
|
||||
type: 'success'
|
||||
},
|
||||
adaptive: {
|
||||
name: 'Адаптивный',
|
||||
type: 'tip'
|
||||
},
|
||||
proprietary: {
|
||||
name: 'Проприетарное',
|
||||
type: 'danger'
|
||||
},
|
||||
restrictions: {
|
||||
name: 'Региональные ограничения',
|
||||
type: 'danger'
|
||||
},
|
||||
altmobile: {
|
||||
name: 'ALT Mobile',
|
||||
type: 'warning'
|
||||
},
|
||||
dontthemes: {
|
||||
name: 'Please don’t theme',
|
||||
type: 'success-1'
|
||||
}
|
||||
},
|
||||
lists: {
|
||||
labels: {
|
||||
metadata_license: 'Лицензия',
|
||||
homepage: 'Сайт проекта',
|
||||
help: 'Помощь',
|
||||
translate: 'Помощь в переводе',
|
||||
bugtracker: 'Сообщить о проблеме'
|
||||
},
|
||||
},
|
||||
links: {
|
||||
sisyphus: {
|
||||
anchor: 'Сизиф',
|
||||
target: '_blank',
|
||||
baseUrl: '//packages.altlinux.org/ru/sisyphus/srpms/',
|
||||
style: '--agw-btn-bg: var(--vp-c-yellow-dimm-1); --agw-btn-color: var(--vp-c-yellow-darker); --agw-btn-hover-bg:var(--vp-c-yellow-dark); --agw-btn-hover-color: var(--vp-c-white);'
|
||||
},
|
||||
flatpak: {
|
||||
anchor: 'Flatpak',
|
||||
target: '_blank',
|
||||
baseUrl: '//flathub.org/ru/apps/',
|
||||
style: '--agw-btn-bg: var(--vp-c-blue-dimm-1); --agw-btn-color: var(--vp-c-blue-darker); --agw-btn-hover-bg:var(--vp-c-blue-dark); --agw-btn-hover-color: var(--vp-c-white);'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -45,8 +103,66 @@ export default defineConfig({
|
||||
lang: 'en',
|
||||
themeConfig: {
|
||||
nav: nav.en,
|
||||
sidebar: sidebar.en
|
||||
}
|
||||
sidebar: sidebar.en,
|
||||
asideMeta: {
|
||||
developer: {
|
||||
label: 'Developer'
|
||||
},
|
||||
keywords: {
|
||||
core: {
|
||||
name: 'GNOME Core',
|
||||
type: 'info'
|
||||
},
|
||||
circle: {
|
||||
name: 'GNOME Circle',
|
||||
type: 'success'
|
||||
},
|
||||
adaptive: {
|
||||
name: 'Adaptive',
|
||||
type: 'tip'
|
||||
},
|
||||
proprietary: {
|
||||
name: 'Proprietary',
|
||||
type: 'danger'
|
||||
},
|
||||
restrictions: {
|
||||
name: 'Regional restrictions',
|
||||
type: 'danger'
|
||||
},
|
||||
altmobile: {
|
||||
name: 'ALT Mobile',
|
||||
type: 'warning'
|
||||
},
|
||||
dontthemes: {
|
||||
name: 'Please don’t theme',
|
||||
type: 'success-1'
|
||||
}
|
||||
},
|
||||
lists: {
|
||||
labels: {
|
||||
metadata_license: 'Licence',
|
||||
homepage: 'Project Website',
|
||||
help: 'Help',
|
||||
translate: 'Contribute Translations',
|
||||
bugtracker: 'Report an Issue'
|
||||
},
|
||||
},
|
||||
links: {
|
||||
sisyphus: {
|
||||
anchor: 'Sisyphus',
|
||||
target: '_blank',
|
||||
baseUrl: '//packages.altlinux.org/en/sisyphus/srpms/',
|
||||
style: '--agw-btn-bg: var(--vp-c-yellow-dimm-1); --agw-btn-color: var(--vp-c-yellow-darker); --agw-btn-hover-bg:var(--vp-c-yellow-dark); --agw-btn-hover-color: var(--vp-c-white);'
|
||||
},
|
||||
flatpak: {
|
||||
anchor: 'Flatpak',
|
||||
target: '_blank',
|
||||
baseUrl: '//flathub.org/apps/',
|
||||
style: '--agw-btn-bg: var(--vp-c-blue-dimm-1); --agw-btn-color: var(--vp-c-blue-darker); --agw-btn-hover-bg:var(--vp-c-blue-dark); --agw-btn-hover-color: var(--vp-c-white);'
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
vite: {
|
||||
|
27
.vitepress/theme/components/AMWAsideMetaKeyword.vue
Normal file
27
.vitepress/theme/components/AMWAsideMetaKeyword.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<script setup lang="ts">
|
||||
export interface Keywords {
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
keywords: Keywords[]
|
||||
}>();
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="badges">
|
||||
<template v-for="keyword in keywords">
|
||||
<Badge :type="keyword.type">{{ keyword.name }}</Badge>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.badges {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
41
.vitepress/theme/components/AMWAsideMetaLink.vue
Normal file
41
.vitepress/theme/components/AMWAsideMetaLink.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
export interface Links {
|
||||
id: string;
|
||||
baseUrl: string;
|
||||
anchor: string;
|
||||
target: string;
|
||||
style: string;
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
links: Links[]
|
||||
}>();
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
{{ links }}
|
||||
<template v-for="link in links">
|
||||
<a :href="(link.baseUrl ?? '') + link.id" :target="link.target" class="btn" :style="link.style">{{ link.anchor }}</a>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.btn {
|
||||
padding: 8px 24px;
|
||||
text-align: center;
|
||||
transition: all .5s ease-in-out;
|
||||
display: grid;
|
||||
background-color: var(--agw-btn-bg);
|
||||
color: var(--agw-btn-color);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: var(--agw-btn-hover-bg);
|
||||
color: var(--agw-btn-hover-color);
|
||||
}
|
||||
</style>
|
58
.vitepress/theme/components/AMWAsideMetaList.vue
Normal file
58
.vitepress/theme/components/AMWAsideMetaList.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<script setup lang="ts">
|
||||
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
|
||||
import { getDomainName } from './../composables/link'
|
||||
|
||||
export interface Lists {
|
||||
label?: string;
|
||||
name?: string;
|
||||
link: string;
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
lists: Lists[]
|
||||
}>();
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<dl>
|
||||
<template v-for="list in lists">
|
||||
<dt v-if="list.label">
|
||||
{{ list.label }}
|
||||
</dt>
|
||||
<dd>
|
||||
<VPLink :href="list.link">{{ list?.name ?? getDomainName(list.link) }} </VPLink>
|
||||
</dd>
|
||||
</template>
|
||||
</dl>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt,
|
||||
dd {
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-size: 12px;
|
||||
color: var(--vp-c-text-2);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-left: 0;
|
||||
font-size: 14px;
|
||||
padding-bottom: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
dd:not(:last-child) {
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
</style>
|
136
.vitepress/theme/components/AMWDocsAsideMeta.vue
Normal file
136
.vitepress/theme/components/AMWDocsAsideMeta.vue
Normal file
@ -0,0 +1,136 @@
|
||||
<script setup lang="ts">
|
||||
import { type Ref, computed } from 'vue'
|
||||
import { mergeConfig, useData } from 'vitepress'
|
||||
import VPImage from 'vitepress/dist/client/theme-default/components/VPImage.vue';
|
||||
|
||||
import { getThumb, getDeveloper, getKeywords, getLists, getLinks } from '../composables/asidemeta'
|
||||
const { frontmatter, theme } = useData()
|
||||
|
||||
import AMWAsideMetaList from './AMWAsideMetaList.vue'
|
||||
import AMWAsideMetaKeyword from './AMWAsideMetaKeyword.vue'
|
||||
import AMWAsideMetaLink from './AMWAsideMetaLink.vue'
|
||||
|
||||
const props = computed(() => {
|
||||
|
||||
if (!frontmatter.value.appstream) {
|
||||
return
|
||||
}
|
||||
|
||||
const { icon, name, summary, developer, url, keywords } = frontmatter.value.appstream
|
||||
const links = frontmatter.value.aggregation
|
||||
const config = theme.value.asideMeta
|
||||
|
||||
return {
|
||||
thumb: getThumb(icon, name),
|
||||
title: summary,
|
||||
keywords: getKeywords(keywords, config.keywords),
|
||||
developer: getDeveloper(developer, config?.developer?.label),
|
||||
lists: getLists(url, config?.lists?.labels),
|
||||
links: getLinks(links, config.links)
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<article v-if="props" class="AMWDocsAsideMeta">
|
||||
<figure class="figure" v-if="props.thumb.src">
|
||||
<VPImage :image="props.thumb.src" :alt="props.thumb.alt" />
|
||||
</figure>
|
||||
<div class="body">
|
||||
<div v-if="props.title" class="title">{{ props.title }}</div>
|
||||
<AMWAsideMetaKeyword :keywords="props.keywords" />
|
||||
<div v-if="props.developer" class="developers">
|
||||
<figure v-if="props.developer?.avatar" class="avatar">
|
||||
<VPImage :image="props.developer?.avatar" :alt="props.developer?.name" />
|
||||
</figure>
|
||||
<div>
|
||||
<div class="caption">{{ props.developer?.label }}</div>
|
||||
<div class="name">{{ props.developer?.name }}
|
||||
<span class="nickname">
|
||||
{{ props.developer?.nickname }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AMWAsideMetaList :lists="props.lists" />
|
||||
<AMWAsideMetaLink :links="props.links" />
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.AMWDocsAsideMeta {
|
||||
overflow: hidden;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 12px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.AMWDocsAsideMeta:hover :deep(.VPImage) {
|
||||
filter: grayscale(0) invert(0);
|
||||
}
|
||||
|
||||
.body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.title:last-child,
|
||||
.title:only-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.figure {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
.figure> :deep(.VPImage) {
|
||||
filter: grayscale(1);
|
||||
transition: filter 0.25s;
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
|
||||
.developers {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
position: relative;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
box-shadow: var(--vp-shadow-3);
|
||||
}
|
||||
|
||||
.caption {
|
||||
font-size: 12px;
|
||||
color: var(--vp-c-text-2);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.name {
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.nickname {
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
color: var(--vp-c-text-3);
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
83
.vitepress/theme/composables/asidemeta.ts
Normal file
83
.vitepress/theme/composables/asidemeta.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { isValidUrl } from './link'
|
||||
|
||||
export const getThumb = (data: any, alt: string) => {
|
||||
|
||||
if (typeof data === 'object' && data.src) {
|
||||
return data
|
||||
} else if (typeof data === 'string' && isValidUrl(data)) {
|
||||
return {
|
||||
src: data,
|
||||
alt: alt
|
||||
}
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
export const getDeveloper = (data: any, label: string) => {
|
||||
|
||||
if (!data.name || !label || typeof data !== 'object') {
|
||||
return
|
||||
}
|
||||
|
||||
return {
|
||||
...{ label: label },
|
||||
...data
|
||||
}
|
||||
}
|
||||
|
||||
export const getLists = (data: any | ArrayLike<unknown>, labels: any) => {
|
||||
|
||||
const _data = {}
|
||||
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
(value && key !== 'donation') ?
|
||||
_data[key] = typeof value !== 'string' ? {
|
||||
...{ label: labels[key] },
|
||||
...value
|
||||
} : {
|
||||
label: labels[key],
|
||||
link: value
|
||||
} : {}
|
||||
})
|
||||
|
||||
return _data
|
||||
}
|
||||
|
||||
export const getKeywords = (data: any, config: {}) => {
|
||||
|
||||
const _data = {}
|
||||
|
||||
if(!data) return
|
||||
|
||||
Object.values(data).forEach((value: any) => {
|
||||
(value && config[value]) ?
|
||||
_data[value] = config[value]
|
||||
: {}
|
||||
})
|
||||
|
||||
return _data
|
||||
|
||||
}
|
||||
|
||||
export const getLinks = (data: any, config: {}) => {
|
||||
|
||||
const _data = {}
|
||||
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
(value && config[key]) ?
|
||||
_data[key] = Object.assign({}, { id: value }, config[key])
|
||||
: {}
|
||||
})
|
||||
|
||||
return _data
|
||||
}
|
||||
|
||||
export const getDonation = (donation: any) => {
|
||||
|
||||
return (donation?.link) ? {
|
||||
donation: donation
|
||||
} : {
|
||||
link: donation
|
||||
}
|
||||
}
|
11
.vitepress/theme/composables/link.ts
Normal file
11
.vitepress/theme/composables/link.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export const isValidUrl = (urlString: string) => {
|
||||
const urlPattern = new RegExp('^(https?:\\/\\/)?'+
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))'+
|
||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+
|
||||
'(\\?[;&a-z\\d%_.~+=-]*)?'+
|
||||
'(\\#[-a-z\\d_]*)?$','i');
|
||||
return !!urlPattern.test(urlString);
|
||||
}
|
||||
|
||||
export const getDomainName = (url: any) => url.match(/\/\/([^/]+)\//)[1].replace('www.', '');
|
@ -14,6 +14,8 @@ import type { Options } from '@nolebase/vitepress-plugin-enhanced-readabilities'
|
||||
import { InjectionKey } from '@nolebase/vitepress-plugin-enhanced-readabilities'
|
||||
import { options as NolebaseEnhancedReadabilitiesOptions } from './plugins/enhanced-readabilities/index'
|
||||
|
||||
import AMWDocsAsideMeta from './components/AMWDocsAsideMeta.vue'
|
||||
|
||||
import './styles/style.css'
|
||||
import './styles/theme.css'
|
||||
import '@nolebase/vitepress-plugin-enhanced-readabilities/dist/style.css'
|
||||
@ -23,7 +25,8 @@ export default {
|
||||
Layout: () => {
|
||||
return h(DefaultTheme.Layout, null, {
|
||||
'nav-bar-content-after': () => h(NolebaseEnhancedReadabilitiesMenu),
|
||||
'nav-screen-content-after': () => h(NolebaseEnhancedReadabilitiesScreenMenu)
|
||||
'nav-screen-content-after': () => h(NolebaseEnhancedReadabilitiesScreenMenu),
|
||||
'aside-outline-after': () => h(AMWDocsAsideMeta),
|
||||
})
|
||||
},
|
||||
enhanceApp({ app, router, siteData }) {
|
||||
|
@ -137,3 +137,18 @@
|
||||
--docsearch-primary-color: var(--vp-c-brand-1) !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component: Badge
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
.VPBadge.success {
|
||||
border-color: transparent;
|
||||
color: var(--vp-c-success-1);
|
||||
background-color: var(--vp-c-success-soft);
|
||||
}
|
||||
|
||||
.VPBadge.success-1 {
|
||||
border-color: transparent;
|
||||
color: var(--vp-c-white);
|
||||
background-color: var(--vp-c-success-2);
|
||||
}
|
||||
|
@ -1,7 +1,24 @@
|
||||
---
|
||||
appstream:
|
||||
aggregation:
|
||||
flatpak: io.bassi.Amberol
|
||||
sisyphus: amberol
|
||||
appstream:
|
||||
id: io.bassi.Amberol
|
||||
name: Amberol
|
||||
icon: https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/io.bassi.Amberol.png
|
||||
summary: Воспроизводит музыку и ничего больше
|
||||
keywords:
|
||||
- adaptive
|
||||
- circle
|
||||
- altmobile
|
||||
developer:
|
||||
name: GNOME
|
||||
metadata_license:
|
||||
name: GNU GPLv3
|
||||
link: https://choosealicense.com/licenses/gpl-3.0/
|
||||
url:
|
||||
homepage: https://gitlab.gnome.org/World/amberol/
|
||||
bugtracker: https://github.com/flathub/com.anydesk.Anydesk/issues
|
||||
---
|
||||
|
||||
# Amberol
|
||||
|
@ -1,7 +1,24 @@
|
||||
---
|
||||
appstream:
|
||||
aggregation:
|
||||
flatpak: io.bassi.Amberol
|
||||
sisyphus: amberol
|
||||
appstream:
|
||||
id: io.bassi.Amberol
|
||||
name: Amberol
|
||||
icon: https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/io.bassi.Amberol.png
|
||||
summary: Plays music, and nothing else
|
||||
keywords:
|
||||
- adaptive
|
||||
- circle
|
||||
- altmobile
|
||||
developer:
|
||||
name: GNOME
|
||||
metadata_license:
|
||||
name: GNU GPLv3
|
||||
link: https://choosealicense.com/licenses/gpl-3.0/
|
||||
url:
|
||||
homepage: https://gitlab.gnome.org/World/amberol/
|
||||
bugtracker: https://github.com/flathub/com.anydesk.Anydesk/issues
|
||||
---
|
||||
|
||||
# Amberol
|
||||
|
Loading…
Reference in New Issue
Block a user