valaxy-theme-hairy 0.0.6 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- package/components/HairyArticleSeries.vue +1 -1
- package/components/HairyBody.vue +1 -1
- package/components/HairyFooter.vue +53 -0
- package/components/HairyHeader.vue +1 -1
- package/components/HairyLayout.vue +3 -4
- package/components/HairyToc.vue +1 -1
- package/components/HairyUserCard.vue +1 -1
- package/components/HairyWaline.vue +4 -0
- package/index.d.ts +43 -0
- package/layouts/hairy.vue +24 -0
- package/layouts/tag.vue +1 -1
- package/modules/loading.scss +4 -0
- package/node/addon-hairy.ts +20 -2
- package/package.json +3 -3
- package/styles/aplayer.scss +76 -0
- package/styles/index.scss +3 -0
- package/valaxy.config.ts +3 -1
@@ -15,7 +15,7 @@ function isCurrent(title = '') {
|
|
15
15
|
</script>
|
16
16
|
|
17
17
|
<template>
|
18
|
-
<div class="pl-16px text-14px relative overflow-hidden">
|
18
|
+
<div class="pl-16px text-14px relative overflow-hidden animate__animated animate__fadeIn">
|
19
19
|
<div class="outline-title">
|
20
20
|
On this Series
|
21
21
|
</div>
|
package/components/HairyBody.vue
CHANGED
@@ -9,7 +9,7 @@ const showWaline = computed(() => route.path.includes('/posts/') || fr.value.wal
|
|
9
9
|
</script>
|
10
10
|
|
11
11
|
<template>
|
12
|
-
<div class="HairyBody min-h-
|
12
|
+
<div class="HairyBody min-h-49vh relative">
|
13
13
|
<div class="mx-auto breakpoint flex z-1 relative">
|
14
14
|
<div class="relative flex-1 pt-2">
|
15
15
|
<slot />
|
@@ -0,0 +1,53 @@
|
|
1
|
+
<script lang="ts" setup>
|
2
|
+
import { capitalize, computed } from 'vue'
|
3
|
+
import { useConfig, useThemeConfig } from 'valaxy'
|
4
|
+
import { useI18n } from 'vue-i18n'
|
5
|
+
|
6
|
+
import pkg from 'valaxy/package.json'
|
7
|
+
|
8
|
+
const { t } = useI18n()
|
9
|
+
|
10
|
+
const config = useConfig()
|
11
|
+
const themeConfig = useThemeConfig()
|
12
|
+
|
13
|
+
const year = new Date().getFullYear()
|
14
|
+
|
15
|
+
const isThisYear = computed(() => {
|
16
|
+
return year === themeConfig.value.footer.since
|
17
|
+
})
|
18
|
+
|
19
|
+
const poweredHtml = computed(() => t('footer.powered', [`<a href="${pkg.repository}" target="_blank" rel="noopener">Valaxy</a> v${pkg.version}`]))
|
20
|
+
const footerIcon = computed(() => themeConfig.value.footer.icon)
|
21
|
+
</script>
|
22
|
+
|
23
|
+
<template>
|
24
|
+
<footer v-if="themeConfig.footer" class="va-footer p-4 pb-10" text="center sm" style="color:var(--va-c-text-light)">
|
25
|
+
<div v-if="themeConfig.footer.beian?.enable && themeConfig.footer.beian.icp" class="beian" m="y-2">
|
26
|
+
<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener">
|
27
|
+
{{ themeConfig.footer.beian.icp }}
|
28
|
+
</a>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
<div class="copyright flex justify-center items-center" p="1">
|
32
|
+
<span>
|
33
|
+
©
|
34
|
+
<template v-if="!isThisYear">
|
35
|
+
{{ themeConfig.footer.since }} -
|
36
|
+
</template>
|
37
|
+
{{ year }}
|
38
|
+
</span>
|
39
|
+
|
40
|
+
<a v-if="footerIcon" class="inline-flex animate-pulse ml-2" :href="footerIcon.url" target="_blank" :title="footerIcon.title">
|
41
|
+
<div :class="footerIcon.name" />
|
42
|
+
</a>
|
43
|
+
|
44
|
+
<span class="ml-2">{{ config.author.name }}</span>
|
45
|
+
</div>
|
46
|
+
|
47
|
+
<div v-if="themeConfig.footer.powered" class="powered" m="2">
|
48
|
+
<span v-html="poweredHtml" /> | <span>{{ t('footer.theme') }} - <a :href="themeConfig.pkg.homepage" :title="`valaxy-theme-${config.theme}`" target="_blank">{{ capitalize(config.theme) }}</a> v{{ themeConfig.pkg.version }}</span>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<slot />
|
52
|
+
</footer>
|
53
|
+
</template>
|
@@ -11,7 +11,7 @@ const { headerRef } = useContext()
|
|
11
11
|
</script>
|
12
12
|
|
13
13
|
<template>
|
14
|
-
<header ref="headerRef" class="HairyHeader relative">
|
14
|
+
<header ref="headerRef" class="HairyHeader relative animate__animated animate__fadeIn">
|
15
15
|
<div class="h-30vh lt-md:h-60vh min-h-80 flex-center">
|
16
16
|
<HairyPostTitle v-if="title" class="relative z-2" :title="title" v-bind="$props">
|
17
17
|
<template #description>
|
@@ -9,7 +9,7 @@ defineProps<{
|
|
9
9
|
</script>
|
10
10
|
|
11
11
|
<template>
|
12
|
-
<div class="HairyLayout">
|
12
|
+
<div class="HairyLayout min-h-100vh">
|
13
13
|
<HairyNav />
|
14
14
|
<HairyHeader v-bind="header">
|
15
15
|
<template #description>
|
@@ -22,8 +22,7 @@ defineProps<{
|
|
22
22
|
<template v-if="$slots['body-slide']" #slide>
|
23
23
|
<slot name="body-slide" />
|
24
24
|
</template>
|
25
|
-
</HairyBody>
|
26
|
-
<
|
27
|
-
<HairyMeting />
|
25
|
+
</HairyBody>
|
26
|
+
<HairyFooter class="z-1 relative" />
|
28
27
|
</div>
|
29
28
|
</template>
|
package/components/HairyToc.vue
CHANGED
@@ -32,7 +32,7 @@ function handleClick({ target: el }: Event) {
|
|
32
32
|
</script>
|
33
33
|
|
34
34
|
<template>
|
35
|
-
<div v-show="resolvedHeaders.length" ref="container">
|
35
|
+
<div v-show="resolvedHeaders.length" ref="container" class="animate__animated animate__fadeIn">
|
36
36
|
<div class="content">
|
37
37
|
<div class="outline-title">
|
38
38
|
{{ themeConfig.outlineTitle || 'On this page' }}
|
@@ -11,7 +11,7 @@ const description = computed(() => theme.value.user?.description || config.value
|
|
11
11
|
</script>
|
12
12
|
|
13
13
|
<template>
|
14
|
-
<div class="pt-5">
|
14
|
+
<div class="pt-5 animate__animated animate__fadeIn">
|
15
15
|
<div class="flex flex-col items-center">
|
16
16
|
<img class="mx-auto w-40 rounded-full -mx-1px" :src="config.author.avatar" />
|
17
17
|
<div class="leading-loose mt-2">
|
package/index.d.ts
CHANGED
@@ -3,6 +3,9 @@ import type { ViteSSGContext } from 'vite-ssg'
|
|
3
3
|
export interface HairyTheme {
|
4
4
|
nav?: NavItem[];
|
5
5
|
home?: {
|
6
|
+
headline?: string
|
7
|
+
title?: string
|
8
|
+
description?: string
|
6
9
|
images?: string[]
|
7
10
|
}
|
8
11
|
user?: {
|
@@ -42,6 +45,46 @@ export interface HairyTheme {
|
|
42
45
|
'storage-name'?: string
|
43
46
|
[key: string]: any
|
44
47
|
}
|
48
|
+
|
49
|
+
footer: Partial<{
|
50
|
+
/**
|
51
|
+
* 建站于
|
52
|
+
*/
|
53
|
+
since: number
|
54
|
+
|
55
|
+
/**
|
56
|
+
* Icon between year and copyright info.
|
57
|
+
*/
|
58
|
+
icon: {
|
59
|
+
/**
|
60
|
+
* icon name, i-xxx
|
61
|
+
*/
|
62
|
+
name: string
|
63
|
+
animated: boolean
|
64
|
+
color: string
|
65
|
+
url: string
|
66
|
+
title: string
|
67
|
+
}
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Powered by valaxy & valaxy-theme-${name}, default is yun
|
71
|
+
*/
|
72
|
+
powered: boolean
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Chinese Users | 中国用户
|
76
|
+
* 备案 ICP
|
77
|
+
* 国内用户需要在网站页脚展示备案 ICP 号
|
78
|
+
* https://beian.miit.gov.cn/
|
79
|
+
*/
|
80
|
+
beian: {
|
81
|
+
enable: boolean
|
82
|
+
/**
|
83
|
+
* 苏ICP备xxxxxxxx号
|
84
|
+
*/
|
85
|
+
icp: string
|
86
|
+
}
|
87
|
+
}>
|
45
88
|
}
|
46
89
|
export interface NavItem {
|
47
90
|
text: string;
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<script lang="ts" setup>
|
2
|
+
import { computed } from 'vue'
|
3
|
+
import { useRoute } from 'vue-router'
|
4
|
+
|
5
|
+
const route = useRoute()
|
6
|
+
const meta = computed(() => route.meta)
|
7
|
+
const type = computed(() => meta.value.type || '')
|
8
|
+
console.log(type.value)
|
9
|
+
</script>
|
10
|
+
|
11
|
+
<template>
|
12
|
+
<HairyBackToTop />
|
13
|
+
<HairyMeting />
|
14
|
+
<home v-if="type === 'home'" />
|
15
|
+
<post v-if="type === 'post'" />
|
16
|
+
<archives v-if="type === 'archives'" />
|
17
|
+
<categories v-if="type === 'categories'" />
|
18
|
+
<month v-if="type === 'month'" />
|
19
|
+
<tag v-if="type === 'tag'" />
|
20
|
+
<tags v-if="type === 'tags'" />
|
21
|
+
<year v-if="type === 'year'" />
|
22
|
+
<default v-if="type === 'default'" />
|
23
|
+
</template>
|
24
|
+
|
package/layouts/tag.vue
CHANGED
package/modules/loading.scss
CHANGED
package/node/addon-hairy.ts
CHANGED
@@ -1,11 +1,29 @@
|
|
1
|
-
import type { ValaxyExtendConfig } from 'valaxy'
|
1
|
+
import type { ResolvedValaxyOptions, ValaxyExtendConfig } from 'valaxy'
|
2
|
+
import type { HairyTheme } from 'valaxy-theme-hairy'
|
2
3
|
|
3
|
-
function addonHairy(): ValaxyExtendConfig {
|
4
|
+
function addonHairy(options: ResolvedValaxyOptions<HairyTheme>): ValaxyExtendConfig {
|
5
|
+
const safelist = options.config.themeConfig?.nav?.filter(v => v.icon)?.map(v => v.icon || '') || []
|
4
6
|
return {
|
5
7
|
extendMd(ctx) {
|
6
8
|
if (ctx.route.meta.excerpt)
|
7
9
|
ctx.route.meta.frontmatter.text = removeTags(ctx.route.meta.excerpt)
|
8
10
|
},
|
11
|
+
pages: {
|
12
|
+
extendRoute(route) {
|
13
|
+
// 改用 type, 由 theme 决定使用布局
|
14
|
+
if (!route.meta.type && route.meta.layout)
|
15
|
+
route.meta.type = route.meta.layout
|
16
|
+
|
17
|
+
if (!route.meta.type)
|
18
|
+
route.meta.type = 'default'
|
19
|
+
|
20
|
+
// 清除所有 layout, 使用统一入口 hairy.vue
|
21
|
+
route.meta.layout = 'hairy'
|
22
|
+
},
|
23
|
+
},
|
24
|
+
unocss: {
|
25
|
+
safelist,
|
26
|
+
},
|
9
27
|
}
|
10
28
|
}
|
11
29
|
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "valaxy-theme-hairy",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.9",
|
4
4
|
"packageManager": "pnpm@7.5.0",
|
5
5
|
"author": {
|
6
6
|
"email": "wwu710632@gmail.com",
|
@@ -27,6 +27,7 @@
|
|
27
27
|
"@iconify-json/simple-icons": "^1.1.19",
|
28
28
|
"@vueuse/core": "^8.9.4",
|
29
29
|
"@waline/client": "^2.6.1",
|
30
|
+
"animate.css": "^4.1.1",
|
30
31
|
"dayjs": "^1.11.4",
|
31
32
|
"defu": "^6.0.0",
|
32
33
|
"element-plus": "^2.2.10",
|
@@ -34,8 +35,7 @@
|
|
34
35
|
"markdown-toc": "^1.2.0",
|
35
36
|
"reading-time": "^1.5.0",
|
36
37
|
"swiper": "^8.3.1",
|
37
|
-
"unoverlay-vue": "0.2.
|
38
|
-
"yaml": "^2.1.1"
|
38
|
+
"unoverlay-vue": "0.2.2"
|
39
39
|
},
|
40
40
|
"devDependencies": {
|
41
41
|
"@types/lodash": "^4.14.182",
|
@@ -0,0 +1,76 @@
|
|
1
|
+
.aplayer.aplayer-fixed .aplayer-list,
|
2
|
+
.aplayer .aplayer-info {
|
3
|
+
font-family: var(--hy-font-family-seto);
|
4
|
+
}
|
5
|
+
|
6
|
+
.dark {
|
7
|
+
.aplayer {
|
8
|
+
background: #2B2B2B;
|
9
|
+
padding: 6px;
|
10
|
+
color: #c2c2c2;
|
11
|
+
}
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
.aplayer.aplayer-fixed .aplayer-body {
|
16
|
+
background-color: #2B2B2B;
|
17
|
+
}
|
18
|
+
|
19
|
+
.aplayer.aplayer-fixed .aplayer-info {
|
20
|
+
border: none;
|
21
|
+
}
|
22
|
+
|
23
|
+
.aplayer .aplayer-miniswitcher {
|
24
|
+
background: #bebebe;
|
25
|
+
}
|
26
|
+
|
27
|
+
.aplayer.aplayer-fixed .aplayer-list {
|
28
|
+
border: none;
|
29
|
+
}
|
30
|
+
|
31
|
+
.aplayer .aplayer-list ol {
|
32
|
+
padding-right: 4px;
|
33
|
+
}
|
34
|
+
|
35
|
+
.aplayer .aplayer-list ol li.aplayer-list-light {
|
36
|
+
background-color: #404040;
|
37
|
+
color: var(--hy-c-primary);
|
38
|
+
|
39
|
+
.aplayer-list-cur {
|
40
|
+
background-color: var(--hy-c-primary) !important;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
.aplayer .aplayer-list ol li {
|
45
|
+
border: none;
|
46
|
+
|
47
|
+
&:hover {
|
48
|
+
background: #373737;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
.aplayer .aplayer-list ol li:nth-child(2n) {
|
53
|
+
background: #2F2F2F;
|
54
|
+
|
55
|
+
&:hover {
|
56
|
+
background: #373737;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
.aplayer .aplayer-list ol li .aplayer-list-index,
|
61
|
+
.aplayer .aplayer-list ol li .aplayer-list-author {
|
62
|
+
color: #8C8C8C;
|
63
|
+
}
|
64
|
+
|
65
|
+
.aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon:hover path {
|
66
|
+
fill: #d9d9d9 !important;
|
67
|
+
}
|
68
|
+
|
69
|
+
.aplayer .aplayer-miniswitcher .aplayer-icon:hover path {
|
70
|
+
// fill: #c2c2c2;
|
71
|
+
}
|
72
|
+
|
73
|
+
.aplayer-pic {
|
74
|
+
// border-radius: 4px;
|
75
|
+
}
|
76
|
+
}
|
package/styles/index.scss
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
@import "./markdown.scss";
|
3
3
|
@import "./element-plus/index.scss";
|
4
4
|
@import "./scrollbar.scss";
|
5
|
+
@import "./aplayer.scss";
|
6
|
+
@import "animate.css";
|
5
7
|
|
6
8
|
body {
|
7
9
|
font-family: var(--hy-font-family-seto);
|
@@ -10,6 +12,7 @@ body {
|
|
10
12
|
|
11
13
|
#app {
|
12
14
|
@apply transition-none;
|
15
|
+
min-height: 100vh;
|
13
16
|
}
|
14
17
|
|
15
18
|
a {
|
package/valaxy.config.ts
CHANGED
@@ -7,11 +7,13 @@ import addonStatistics from './node/addon-statistics'
|
|
7
7
|
import addonToc from './node/addon-toc'
|
8
8
|
export default defineTheme<HairyTheme>((options) => {
|
9
9
|
const images = addonImages(options)
|
10
|
+
const hairy = addonHairy(options)
|
10
11
|
|
11
12
|
return {
|
12
13
|
vite: images.vite,
|
14
|
+
pages: hairy.pages,
|
13
15
|
extendMd(ctx) {
|
14
|
-
|
16
|
+
hairy.extendMd?.(ctx)
|
15
17
|
images.extendMd?.(ctx)
|
16
18
|
addonStatistics().extendMd?.(ctx)
|
17
19
|
addonToc().extendMd?.(ctx)
|