valaxy-theme-press 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/index.ts +1 -0
- package/components/DocsBoard.vue +2 -2
- package/components/PressArticle.vue +15 -10
- package/components/PressArticleCard.vue +6 -2
- package/components/PressAside.vue +21 -22
- package/components/PressButton.vue +5 -12
- package/components/PressCategories.vue +24 -3
- package/components/PressCategory.vue +14 -7
- package/components/PressDocFooter.vue +15 -0
- package/components/PressDocFooterLastUpdated.vue +44 -0
- package/components/PressFeature.vue +1 -1
- package/components/PressFooter.vue +53 -0
- package/components/PressHome.vue +1 -7
- package/components/{PressToc.vue → PressOutline.vue} +13 -39
- package/components/PressOutlineItem.vue +48 -0
- package/components/PressSidebar.vue +26 -6
- package/components/ValaxyMain.vue +17 -12
- package/components/nav/PressNavBar.vue +20 -32
- package/components/nav/PressNavItemGroup.vue +101 -0
- package/components/nav/PressNavItemLink.vue +39 -0
- package/composables/edit-link.ts +14 -0
- package/composables/index.ts +1 -0
- package/config/index.ts +8 -2
- package/layouts/layout.vue +5 -2
- package/package.json +15 -5
- package/setup/main.ts +1 -2
- package/styles/css-vars.scss +9 -6
- package/styles/helper.scss +0 -10
- package/styles/markdown.scss +10 -1
- package/types/index.d.ts +59 -21
- package/valaxy.config.ts +2 -0
- package/LICENSE +0 -21
package/client/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../composables'
|
package/components/DocsBoard.vue
CHANGED
|
@@ -10,9 +10,9 @@ const { t } = useI18n()
|
|
|
10
10
|
|
|
11
11
|
<ul>
|
|
12
12
|
<li>
|
|
13
|
-
<
|
|
13
|
+
<router-link to="/docs" :title="t('docs.view_docs')">
|
|
14
14
|
{{ t('docs.view_docs') }}
|
|
15
|
-
</
|
|
15
|
+
</router-link>
|
|
16
16
|
</li>
|
|
17
17
|
<li>
|
|
18
18
|
<router-link class="flex justify-center" to="/examples">
|
|
@@ -17,15 +17,14 @@ const prevPost = computed(() => posts.value[findCurrentIndex() + 1])
|
|
|
17
17
|
</script>
|
|
18
18
|
|
|
19
19
|
<template>
|
|
20
|
-
<article class="xl:divide-y xl:divide-gray-200">
|
|
21
|
-
<header class="pt-
|
|
20
|
+
<article class="xl:divide-y xl:divide-gray-200 max-w-7xl m-auto" p="x-6" w="full">
|
|
21
|
+
<header class="pt-20 xl:pb-10 space-y-1 text-center">
|
|
22
22
|
<PressDate :date="frontmatter.date" />
|
|
23
23
|
<h1
|
|
24
24
|
class="
|
|
25
25
|
text-3xl
|
|
26
26
|
leading-9
|
|
27
27
|
font-extrabold
|
|
28
|
-
text-gray-900
|
|
29
28
|
tracking-tight
|
|
30
29
|
sm:text-4xl sm:leading-10
|
|
31
30
|
md:text-5xl md:leading-14
|
|
@@ -40,14 +39,14 @@ const prevPost = computed(() => posts.value[findCurrentIndex() + 1])
|
|
|
40
39
|
divide-y
|
|
41
40
|
xl:divide-y-0
|
|
42
41
|
divide-gray-200
|
|
43
|
-
xl:grid xl:grid-cols-
|
|
42
|
+
xl:grid xl:grid-cols-12 xl:gap-x-6
|
|
44
43
|
pb-16
|
|
45
44
|
xl:pb-20
|
|
46
45
|
"
|
|
47
46
|
style="grid-template-rows: auto 1fr"
|
|
48
47
|
>
|
|
49
48
|
<PressAuthor v-if="frontmatter.author" :frontmatter="frontmatter" />
|
|
50
|
-
<div class="divide-y divide-gray-200 xl:pb-0 xl:col-span-
|
|
49
|
+
<div class="divide-y divide-gray-200 xl:pb-0 xl:col-span-8 xl:row-span-2">
|
|
51
50
|
<router-view />
|
|
52
51
|
</div>
|
|
53
52
|
|
|
@@ -57,7 +56,7 @@ const prevPost = computed(() => posts.value[findCurrentIndex() + 1])
|
|
|
57
56
|
font-medium
|
|
58
57
|
leading-5
|
|
59
58
|
divide-y divide-gray-200
|
|
60
|
-
xl:col-start-1 xl:row-start-2
|
|
59
|
+
xl:col-start-1 xl:row-start-2 xl:col-span-2
|
|
61
60
|
"
|
|
62
61
|
>
|
|
63
62
|
<div v-if="nextPost" class="py-8">
|
|
@@ -65,19 +64,25 @@ const prevPost = computed(() => posts.value[findCurrentIndex() + 1])
|
|
|
65
64
|
Next Article
|
|
66
65
|
</h2>
|
|
67
66
|
<div class="link">
|
|
68
|
-
<
|
|
67
|
+
<router-link :to="nextPost.href">
|
|
68
|
+
{{ nextPost.title }}
|
|
69
|
+
</router-link>
|
|
69
70
|
</div>
|
|
70
71
|
</div>
|
|
71
|
-
<div v-if="prevPost" class="py-8">
|
|
72
|
+
<div v-if="prevPost && prevPost.href" class="py-8">
|
|
72
73
|
<h2 class="text-xs tracking-wide uppercase text-gray-500">
|
|
73
74
|
Previous Article
|
|
74
75
|
</h2>
|
|
75
76
|
<div class="link">
|
|
76
|
-
<
|
|
77
|
+
<router-link :to="prevPost.href">
|
|
78
|
+
{{ prevPost.title }}
|
|
79
|
+
</router-link>
|
|
77
80
|
</div>
|
|
78
81
|
</div>
|
|
79
82
|
<div class="pt-8">
|
|
80
|
-
<
|
|
83
|
+
<router-link class="link" to="/">
|
|
84
|
+
← Back to Home
|
|
85
|
+
</router-link>
|
|
81
86
|
</div>
|
|
82
87
|
</footer>
|
|
83
88
|
</div>
|
|
@@ -12,7 +12,9 @@ defineProps<{
|
|
|
12
12
|
<div class="space-y-5 xl:col-span-3">
|
|
13
13
|
<div class="space-y-6">
|
|
14
14
|
<h2 class="text-2xl leading-8 font-bold tracking-tight">
|
|
15
|
-
<
|
|
15
|
+
<router-link class="text-gray-900" :to="post.path || ''">
|
|
16
|
+
{{ post.title }}
|
|
17
|
+
</router-link>
|
|
16
18
|
</h2>
|
|
17
19
|
<div
|
|
18
20
|
v-if="post.excerpt"
|
|
@@ -21,7 +23,9 @@ defineProps<{
|
|
|
21
23
|
/>
|
|
22
24
|
</div>
|
|
23
25
|
<div class="text-base leading-6 font-medium">
|
|
24
|
-
<
|
|
26
|
+
<router-link class="link" aria-label="read more" :to="post.path || ''">
|
|
27
|
+
Read more →
|
|
28
|
+
</router-link>
|
|
25
29
|
</div>
|
|
26
30
|
</div>
|
|
27
31
|
</article>
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
|
|
3
|
-
import { useData, useFrontmatter } from 'valaxy'
|
|
2
|
+
import { useFrontmatter } from 'valaxy'
|
|
4
3
|
import { useAppStore } from 'valaxy/client/stores/app'
|
|
4
|
+
import PressOutline from './PressOutline.vue'
|
|
5
5
|
|
|
6
6
|
const frontmatter = useFrontmatter()
|
|
7
|
-
const data = useData()
|
|
8
|
-
// const { t } = useI18n()
|
|
9
7
|
const app = useAppStore()
|
|
10
8
|
</script>
|
|
11
9
|
|
|
12
10
|
<template>
|
|
13
11
|
<button
|
|
14
|
-
class="
|
|
15
|
-
|
|
12
|
+
class="toc-btn shadow-lg fixed press-icon-btn z-99 xl:hidden!"
|
|
13
|
+
right="5" bottom="8"
|
|
16
14
|
@click="app.toggleRightSidebar()"
|
|
17
15
|
>
|
|
18
16
|
<div i-ri-file-list-line />
|
|
@@ -21,14 +19,14 @@ const app = useAppStore()
|
|
|
21
19
|
<ValaxyOverlay :show="app.isRightSidebarOpen" @click="app.toggleRightSidebar()" />
|
|
22
20
|
|
|
23
21
|
<aside
|
|
24
|
-
class="press-aside lt-xl:fixed
|
|
25
|
-
press-card xl:(shadow-none hover:shadow-none)
|
|
26
|
-
p="l-0 xl:l-
|
|
27
|
-
z="
|
|
22
|
+
class="press-aside lt-xl:fixed shadow
|
|
23
|
+
press-card xl:(shadow-none hover:shadow-none) hover:shadow-lg"
|
|
24
|
+
p="l-0 xl:l-8" text="center"
|
|
25
|
+
z="5"
|
|
28
26
|
:class="app.isRightSidebarOpen && 'open'"
|
|
29
27
|
>
|
|
30
28
|
<div class="aside-container lt-xl:fixed" flex="~ col">
|
|
31
|
-
<
|
|
29
|
+
<PressOutline v-if="frontmatter.toc !== false" />
|
|
32
30
|
<div class="flex-grow" />
|
|
33
31
|
<div v-if="$slots.default" class="custom-container">
|
|
34
32
|
<slot />
|
|
@@ -41,23 +39,24 @@ const app = useAppStore()
|
|
|
41
39
|
@use 'valaxy/client/styles/mixins' as *;
|
|
42
40
|
|
|
43
41
|
.press-card{
|
|
44
|
-
box-shadow: none;
|
|
45
42
|
background-color: var(--va-c-bg);
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
.press-aside {
|
|
49
|
-
position: relative;
|
|
50
|
-
min-width: 272px;
|
|
51
|
-
transform: translateX(100%);
|
|
52
46
|
top: 0;
|
|
53
47
|
bottom: 0;
|
|
54
48
|
right: 0;
|
|
55
|
-
z-index:
|
|
49
|
+
z-index: var(--pr-z-index-aside);
|
|
50
|
+
width: var(--va-aside-width);
|
|
51
|
+
|
|
52
|
+
transform: translateX(100%);
|
|
56
53
|
|
|
57
54
|
transition: box-shadow var(--va-transition-duration), opacity 0.25s,
|
|
58
55
|
transform var(--va-transition-duration) cubic-bezier(0.19, 1, 0.22, 1);
|
|
59
56
|
|
|
60
57
|
&.open {
|
|
58
|
+
position: fixed;
|
|
59
|
+
right: 0;
|
|
61
60
|
display: block;
|
|
62
61
|
transform: translateX(0);
|
|
63
62
|
}
|
|
@@ -65,10 +64,10 @@ const app = useAppStore()
|
|
|
65
64
|
|
|
66
65
|
.aside-container {
|
|
67
66
|
position: sticky;
|
|
68
|
-
top:
|
|
69
|
-
margin-top: calc(var(--pr-nav-height) * -1 -
|
|
70
|
-
padding-top: calc(var(--pr-nav-height) +
|
|
71
|
-
height: 100vh;
|
|
67
|
+
top: 0;
|
|
68
|
+
margin-top: calc(var(--pr-nav-height) * -1 - 20px);
|
|
69
|
+
padding-top: calc(var(--pr-nav-height) + 20px);
|
|
70
|
+
height: calc(100vh - var(--pr-nav-height) - 32px);
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
@include media('xl') {
|
|
@@ -82,7 +81,7 @@ const app = useAppStore()
|
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
.toc-btn {
|
|
85
|
-
color: var(--va-c-
|
|
86
|
-
background-color: var(--va-c-
|
|
84
|
+
color: var(--va-c-bg);
|
|
85
|
+
background-color: var(--va-c-primary);
|
|
87
86
|
}
|
|
88
87
|
</style>
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { computed } from 'vue'
|
|
3
|
-
import { useRouter } from 'vue-router'
|
|
4
|
-
import { EXTERNAL_URL_RE } from 'valaxy'
|
|
5
3
|
|
|
6
4
|
const props = defineProps<{
|
|
7
5
|
theme: 'brand' | 'alt'
|
|
@@ -9,9 +7,6 @@ const props = defineProps<{
|
|
|
9
7
|
text: string
|
|
10
8
|
}>()
|
|
11
9
|
|
|
12
|
-
const isUrl = computed(() => EXTERNAL_URL_RE.test(props.link))
|
|
13
|
-
const router = useRouter()
|
|
14
|
-
|
|
15
10
|
const classes = computed(() => {
|
|
16
11
|
const arr = []
|
|
17
12
|
if (props.theme === 'brand')
|
|
@@ -24,15 +19,13 @@ const classes = computed(() => {
|
|
|
24
19
|
</script>
|
|
25
20
|
|
|
26
21
|
<template>
|
|
27
|
-
<
|
|
28
|
-
:
|
|
22
|
+
<AppLink
|
|
23
|
+
:to="link"
|
|
29
24
|
m="2"
|
|
30
25
|
:class="classes"
|
|
31
|
-
class="sese-btn btn" bg="gradient-to-r"
|
|
32
|
-
|
|
33
|
-
:target="isUrl ? '_blank' : undefined"
|
|
34
|
-
@click="!isUrl && router.push(link)"
|
|
26
|
+
class="sese-btn btn rounded-full hover:shadow-lg" bg="gradient-to-r"
|
|
27
|
+
p="x-6"
|
|
35
28
|
>
|
|
36
29
|
{{ text }}
|
|
37
|
-
</
|
|
30
|
+
</AppLink>
|
|
38
31
|
</template>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import { useThemeConfig } from 'valaxy'
|
|
2
3
|
import type { Categories } from 'valaxy'
|
|
3
|
-
import { ref } from 'vue'
|
|
4
|
+
import { computed, ref } from 'vue'
|
|
4
5
|
|
|
5
6
|
const props = withDefaults(defineProps<{
|
|
6
7
|
categories: Categories
|
|
@@ -16,15 +17,31 @@ const props = withDefaults(defineProps<{
|
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
const collapsable = ref(props.collapsable)
|
|
20
|
+
|
|
21
|
+
const themeConfig = useThemeConfig()
|
|
22
|
+
const sidebar = computed(() => themeConfig.value.sidebar)
|
|
19
23
|
</script>
|
|
20
24
|
|
|
21
25
|
<template>
|
|
22
|
-
<ul v-for="
|
|
23
|
-
<PressCategory
|
|
26
|
+
<ul v-for="item in sidebar" :key="item" class="category-list">
|
|
27
|
+
<PressCategory
|
|
28
|
+
v-if="categories.get(item)"
|
|
29
|
+
:name="item" :category="categories.get(item)"
|
|
30
|
+
:level="level + 1"
|
|
31
|
+
:display-category="displayCategory"
|
|
32
|
+
:collapsable="collapsable"
|
|
33
|
+
/>
|
|
24
34
|
</ul>
|
|
25
35
|
</template>
|
|
26
36
|
|
|
27
37
|
<style lang="scss">
|
|
38
|
+
.category-list {
|
|
39
|
+
&:first-child {
|
|
40
|
+
.category-list-item {
|
|
41
|
+
border-top: 0px;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
28
45
|
.post-list-item {
|
|
29
46
|
a {
|
|
30
47
|
color: var(--va-c-text-light);
|
|
@@ -47,4 +64,8 @@ const collapsable = ref(props.collapsable)
|
|
|
47
64
|
}
|
|
48
65
|
}
|
|
49
66
|
}
|
|
67
|
+
|
|
68
|
+
.category-list+.category-list {
|
|
69
|
+
margin-top: 1rem;
|
|
70
|
+
}
|
|
50
71
|
</style>
|
|
@@ -23,24 +23,31 @@ const collapsable = ref(props.collapsable)
|
|
|
23
23
|
const { t, locale } = useI18n()
|
|
24
24
|
|
|
25
25
|
const getTitle = (post: Post | any) => {
|
|
26
|
-
const lang = locale.value
|
|
26
|
+
const lang = locale.value
|
|
27
27
|
return post[`title_${lang}`] ? post[`title_${lang}`] : post.title
|
|
28
28
|
}
|
|
29
29
|
</script>
|
|
30
30
|
|
|
31
31
|
<template>
|
|
32
|
-
<li
|
|
33
|
-
|
|
32
|
+
<li
|
|
33
|
+
v-if="category.total"
|
|
34
|
+
p="t-2"
|
|
35
|
+
w="full" border="t t-$pr-c-divider-light"
|
|
36
|
+
class="category-list-item inline-flex items-center justify-between"
|
|
37
|
+
>
|
|
38
|
+
<span class="category-name" font="bold" m="l-1" @click="displayCategory ? displayCategory(name) : null">
|
|
39
|
+
{{ name === 'Uncategorized' ? t('category.uncategorized') : name }}
|
|
40
|
+
<!-- <sup font="normal">[{{ category.total }}]</sup> -->
|
|
41
|
+
</span>
|
|
42
|
+
<span class="folder-action inline-flex cursor-pointer" opacity="50" @click="collapsable = !collapsable">
|
|
34
43
|
<div v-if="collapsable" i-ri-folder-add-line />
|
|
35
|
-
<div v-else
|
|
36
|
-
<span class="category-name" m="l-1" @click="displayCategory ? displayCategory(name) : null">
|
|
37
|
-
{{ name === 'Uncategorized' ? t('category.uncategorized') : name }} [{{ category.total }}]
|
|
44
|
+
<div v-else i-ri-folder-reduce-line />
|
|
38
45
|
</span>
|
|
39
46
|
</li>
|
|
40
47
|
|
|
41
48
|
<template v-if="!collapsable">
|
|
42
49
|
<ul v-if="!isParentCategory(category)">
|
|
43
|
-
<li v-for="post, i in category.posts" :key="i" class="post-list-item"
|
|
50
|
+
<li v-for="post, i in category.posts" :key="i" class="post-list-item">
|
|
44
51
|
<router-link v-if="post.title" :to="post.path || ''" class="inline-flex items-center" active-class="active">
|
|
45
52
|
<span m="l-1" text="sm">{{ getTitle(post) }}</span>
|
|
46
53
|
</router-link>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { useEditLink } from '../composables'
|
|
3
|
+
|
|
4
|
+
const editLink = useEditLink()
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<div flex justify="between" text="sm">
|
|
9
|
+
<a flex items="center" :href="editLink.url" target="_blank">
|
|
10
|
+
<div i-ri-external-link-line />
|
|
11
|
+
<span ml-1>{{ editLink.text }}</span>
|
|
12
|
+
</a>
|
|
13
|
+
<PressDocFooterLastUpdated />
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, onMounted, ref, watchEffect } from 'vue'
|
|
3
|
+
import { useData, useThemeConfig } from 'valaxy'
|
|
4
|
+
|
|
5
|
+
const data = useData()
|
|
6
|
+
const themeConfig = useThemeConfig()
|
|
7
|
+
|
|
8
|
+
const date = computed(() => new Date(data.lastUpdated!))
|
|
9
|
+
const isoDatetime = computed(() => date.value.toISOString())
|
|
10
|
+
const datetime = ref('')
|
|
11
|
+
|
|
12
|
+
// set time on mounted hook because the locale string might be different
|
|
13
|
+
// based on end user and will lead to potential hydration mismatch if
|
|
14
|
+
// calculated at build time
|
|
15
|
+
onMounted(() => {
|
|
16
|
+
watchEffect(() => {
|
|
17
|
+
datetime.value = date.value.toLocaleString(window.navigator.language)
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<p class="press-lastUpdated">
|
|
24
|
+
{{ themeConfig.lastUpdatedText ?? 'Last updated' }}:
|
|
25
|
+
<time :datetime="isoDatetime">{{ datetime }}</time>
|
|
26
|
+
</p>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<style scoped>
|
|
30
|
+
.press-lastUpdated {
|
|
31
|
+
line-height: 24px;
|
|
32
|
+
font-size: 14px;
|
|
33
|
+
font-weight: 500;
|
|
34
|
+
color: var(--va-c-text-light);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@media (min-width: 640px) {
|
|
38
|
+
.press-lastUpdated {
|
|
39
|
+
line-height: 32px;
|
|
40
|
+
font-size: 14px;
|
|
41
|
+
font-weight: 500;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
</style>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useSidebar } from 'valaxy'
|
|
3
|
+
import { useThemeConfig } from '../composables'
|
|
4
|
+
|
|
5
|
+
const themeConfig = useThemeConfig()
|
|
6
|
+
const { hasSidebar } = useSidebar()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<footer v-if="themeConfig.footer" class="press-footer" :class="{ 'has-sidebar': hasSidebar }">
|
|
11
|
+
<div flex="~ col" class="container">
|
|
12
|
+
<p v-if="themeConfig.footer.message" class="message" v-html="themeConfig.footer.message" />
|
|
13
|
+
<p v-if="themeConfig.footer.copyright" class="copyright" v-html="themeConfig.footer.copyright" />
|
|
14
|
+
</div>
|
|
15
|
+
</footer>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<style lang="scss" scoped>
|
|
19
|
+
.press-footer {
|
|
20
|
+
position: relative;
|
|
21
|
+
z-index: var(--pr-z-index-footer);
|
|
22
|
+
border-top: 1px solid var(--pr-c-divider-light);
|
|
23
|
+
padding: 32px 24px;
|
|
24
|
+
background-color: var(--va-c-bg);
|
|
25
|
+
|
|
26
|
+
&.has-sidebar {
|
|
27
|
+
display: none;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@media (min-width: 768px) {
|
|
32
|
+
.VPFooter {
|
|
33
|
+
padding: 32px;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.container {
|
|
38
|
+
margin: 0 auto;
|
|
39
|
+
max-width: var(--pr-layout-max-width);
|
|
40
|
+
text-align: center;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.message,
|
|
44
|
+
.copyright {
|
|
45
|
+
line-height: 24px;
|
|
46
|
+
font-size: 14px;
|
|
47
|
+
font-weight: 500;
|
|
48
|
+
color: var(--va-c-text-lighter);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.message { order: 2; }
|
|
52
|
+
.copyright { order: 1; }
|
|
53
|
+
</style>
|
package/components/PressHome.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="press-home">
|
|
2
|
+
<div class="press-home" p="x-6">
|
|
3
3
|
<slot name="home-hero-before" />
|
|
4
4
|
<PressHomeHero />
|
|
5
5
|
<slot name="home-hero-after" />
|
|
@@ -11,11 +11,5 @@
|
|
|
11
11
|
<slot>
|
|
12
12
|
<router-view />
|
|
13
13
|
</slot>
|
|
14
|
-
|
|
15
|
-
<p align="center">
|
|
16
|
-
<a href="https://sponsors.yunyoujun.cn">
|
|
17
|
-
<img src="https://sponsors.yunyoujun.cn/sponsors.svg">
|
|
18
|
-
</a>
|
|
19
|
-
</p>
|
|
20
14
|
</div>
|
|
21
15
|
</template>
|
|
@@ -1,38 +1,25 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import { useI18n } from 'vue-i18n'
|
|
4
|
-
import type { Header } from 'valaxy'
|
|
2
|
+
import { ref } from 'vue'
|
|
5
3
|
import {
|
|
6
|
-
resolveHeaders,
|
|
7
4
|
useActiveAnchor,
|
|
8
|
-
|
|
5
|
+
useOutline,
|
|
9
6
|
} from 'valaxy'
|
|
7
|
+
import { useI18n } from 'vue-i18n'
|
|
10
8
|
import { useThemeConfig } from '../composables'
|
|
11
9
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const frontmatter = useFrontmatter()
|
|
10
|
+
const { t } = useI18n()
|
|
15
11
|
const themeConfig = useThemeConfig()
|
|
16
12
|
|
|
17
|
-
const { locale, t } = useI18n()
|
|
18
13
|
const container = ref()
|
|
19
14
|
const marker = ref()
|
|
20
15
|
|
|
21
16
|
useActiveAnchor(container, marker)
|
|
22
17
|
|
|
23
|
-
const
|
|
24
|
-
return resolveHeaders(props.headers || [])
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
function handleClick({ target: el }: Event) {
|
|
28
|
-
const id = `#${(el as HTMLAnchorElement).href!.split('#')[1]}`
|
|
29
|
-
const heading = document.querySelector(decodeURIComponent(id)) as HTMLAnchorElement
|
|
30
|
-
heading?.focus()
|
|
31
|
-
}
|
|
18
|
+
const { headers, handleClick } = useOutline()
|
|
32
19
|
</script>
|
|
33
20
|
|
|
34
21
|
<template>
|
|
35
|
-
<div v-show="headers.length" ref="container"
|
|
22
|
+
<div v-show="headers.length" ref="container">
|
|
36
23
|
<div class="content">
|
|
37
24
|
<div class="outline-title">
|
|
38
25
|
{{ themeConfig.outlineTitle || t('sidebar.toc') }}
|
|
@@ -45,26 +32,12 @@ function handleClick({ target: el }: Event) {
|
|
|
45
32
|
Table of Contents for current page
|
|
46
33
|
</span>
|
|
47
34
|
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
:lang="lang || locale"
|
|
55
|
-
>
|
|
56
|
-
<a class="outline-link" :href="link" @click="handleClick">
|
|
57
|
-
{{ text }}
|
|
58
|
-
</a>
|
|
59
|
-
<ul v-if="children && frontmatter.outline === 'deep'">
|
|
60
|
-
<li v-for="item in children" v-show="!item.hidden" :key="item.link" :lang="lang || locale">
|
|
61
|
-
<a class="outline-link" p="l-3" :href="link" @click="handleClick">
|
|
62
|
-
{{ item.text }}
|
|
63
|
-
</a>
|
|
64
|
-
</li>
|
|
65
|
-
</ul>
|
|
66
|
-
</li>
|
|
67
|
-
</ul>
|
|
35
|
+
<PressOutlineItem
|
|
36
|
+
class="va-toc relative z-1"
|
|
37
|
+
:headers="headers"
|
|
38
|
+
:on-click="handleClick"
|
|
39
|
+
root
|
|
40
|
+
/>
|
|
68
41
|
</nav>
|
|
69
42
|
</div>
|
|
70
43
|
</div>
|
|
@@ -106,6 +79,7 @@ function handleClick({ target: el }: Event) {
|
|
|
106
79
|
line-height: 28px;
|
|
107
80
|
font-size: 14px;
|
|
108
81
|
font-weight: 600;
|
|
82
|
+
color: var(--pr-c-text-1);
|
|
109
83
|
}
|
|
110
84
|
|
|
111
85
|
.outline-link {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { MenuItem } from 'valaxy'
|
|
3
|
+
import { useI18n } from 'vue-i18n'
|
|
4
|
+
|
|
5
|
+
defineProps<{
|
|
6
|
+
headers: MenuItem[]
|
|
7
|
+
onClick: (e: MouseEvent) => void
|
|
8
|
+
root?: boolean
|
|
9
|
+
}>()
|
|
10
|
+
|
|
11
|
+
const { locale } = useI18n()
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<ul :class="root ? 'root' : 'nested'">
|
|
16
|
+
<li v-for="{ children, link, title, lang } in headers" :key="link" class="va-toc-item" :lang="lang || locale">
|
|
17
|
+
<a class="outline-link" :href="link" @click="onClick">{{ title }}</a>
|
|
18
|
+
<template v-if="children?.length">
|
|
19
|
+
<PressOutlineItem :headers="children" :on-click="onClick" />
|
|
20
|
+
</template>
|
|
21
|
+
</li>
|
|
22
|
+
</ul>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<style lang="scss" scoped>
|
|
26
|
+
.va-toc {
|
|
27
|
+
.va-toc-item {
|
|
28
|
+
.outline-link {
|
|
29
|
+
color: var(--va-c-text-light);
|
|
30
|
+
white-space: nowrap;
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
text-overflow: ellipsis;
|
|
33
|
+
transition: color 0.5s;
|
|
34
|
+
|
|
35
|
+
&:hover,
|
|
36
|
+
&.active {
|
|
37
|
+
color: var(--va-c-brand);
|
|
38
|
+
transition: color 0.25s;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.nested {
|
|
44
|
+
padding-left: 0.8rem;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
</style>
|
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import { computed } from 'vue'
|
|
2
3
|
import { useCategory, usePageList, useSidebar } from 'valaxy'
|
|
4
|
+
import { useThemeConfig } from '../composables'
|
|
3
5
|
|
|
4
6
|
defineProps<{
|
|
5
7
|
open: boolean
|
|
6
8
|
}>()
|
|
7
9
|
|
|
8
10
|
const pages = usePageList()
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
+
const themeConfig = useThemeConfig()
|
|
12
|
+
|
|
13
|
+
const categories = computed(() => {
|
|
14
|
+
const cs = useCategory('', pages.value)
|
|
15
|
+
cs.children.delete('Uncategorized')
|
|
16
|
+
|
|
17
|
+
const sidebar = themeConfig.value.sidebar
|
|
18
|
+
if (sidebar) {
|
|
19
|
+
cs.children.forEach((_, key) => {
|
|
20
|
+
if (!themeConfig.value.sidebar.includes(key))
|
|
21
|
+
cs.children.delete(key)
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
return cs
|
|
25
|
+
})
|
|
11
26
|
|
|
12
27
|
const { hasSidebar } = useSidebar()
|
|
13
28
|
</script>
|
|
@@ -32,8 +47,8 @@ const { hasSidebar } = useSidebar()
|
|
|
32
47
|
top: 0;
|
|
33
48
|
bottom: 0;
|
|
34
49
|
left: 0;
|
|
35
|
-
padding:
|
|
36
|
-
|
|
50
|
+
padding: 1rem;
|
|
51
|
+
top: var(--pr-nav-height);
|
|
37
52
|
z-index: var(--pr-z-index-sidebar);
|
|
38
53
|
width: calc(100vw - 64px);
|
|
39
54
|
max-width: 320px;
|
|
@@ -41,6 +56,7 @@ const { hasSidebar } = useSidebar()
|
|
|
41
56
|
opacity: 0;
|
|
42
57
|
overflow-x: hidden;
|
|
43
58
|
overflow-y: auto;
|
|
59
|
+
overflow-y: overlay;
|
|
44
60
|
transform: translateX(-100%);
|
|
45
61
|
transition: opacity 0.5s, transform 0.25s ease;
|
|
46
62
|
|
|
@@ -55,8 +71,6 @@ const { hasSidebar } = useSidebar()
|
|
|
55
71
|
@include media('md') {
|
|
56
72
|
.press-sidebar {
|
|
57
73
|
z-index: 1;
|
|
58
|
-
padding: 1.5rem 1rem;
|
|
59
|
-
padding-top: var(--pr-nav-height);
|
|
60
74
|
width: var(--va-sidebar-width);
|
|
61
75
|
max-width: 100%;
|
|
62
76
|
background-color: var(--va-c-bg-alt);
|
|
@@ -65,4 +79,10 @@ const { hasSidebar } = useSidebar()
|
|
|
65
79
|
transform: translateX(0);
|
|
66
80
|
}
|
|
67
81
|
}
|
|
82
|
+
|
|
83
|
+
@include mobile {
|
|
84
|
+
.press-sidebar {
|
|
85
|
+
top: 0;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
68
88
|
</style>
|
|
@@ -20,23 +20,28 @@ const isHome = useLayout('home')
|
|
|
20
20
|
'has-sidebar': hasSidebar,
|
|
21
21
|
}"
|
|
22
22
|
>
|
|
23
|
-
<div
|
|
23
|
+
<div
|
|
24
|
+
w="full" flex="~" :class="{
|
|
25
|
+
'px-6 md:pl-12': hasSidebar,
|
|
26
|
+
}" p="t-4"
|
|
27
|
+
>
|
|
24
28
|
<slot name="main">
|
|
25
|
-
<div class="content"
|
|
29
|
+
<div class="content" w="full" :class="{ 'm-auto': !hasSidebar }" flex="~ col grow" p="lt-md:0">
|
|
26
30
|
<slot name="main-header" />
|
|
27
31
|
<slot name="main-header-after" />
|
|
28
32
|
|
|
29
33
|
<slot name="main-content">
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
<ValaxyMd class="prose mx-auto w-full max-w-4xl" :frontmatter="frontmatter">
|
|
35
|
+
<h1 v-if="hasSidebar && !isHome && frontmatter.title" :id="frontmatter.title" tabindex="-1">
|
|
36
|
+
{{ frontmatter.title }}
|
|
37
|
+
<a class="header-anchor" :href="`#${frontmatter.title}`" aria-hidden="true">#</a>
|
|
38
|
+
</h1>
|
|
39
|
+
<slot name="main-content-md" />
|
|
40
|
+
<slot />
|
|
41
|
+
</ValaxyMd>
|
|
42
|
+
|
|
43
|
+
<PressDocFooter v-if="!isHome" class="pb-8 max-w-4xl" w="full" m="auto" />
|
|
44
|
+
|
|
40
45
|
<slot name="main-content-after" />
|
|
41
46
|
</slot>
|
|
42
47
|
</div>
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { useConfig, useSidebar } from 'valaxy'
|
|
3
3
|
import { useThemeConfig } from '../../composables'
|
|
4
4
|
import PressSwitchAppearance from './PressSwitchAppearance.vue'
|
|
5
|
+
import PressNavItemLink from './PressNavItemLink.vue'
|
|
6
|
+
import PressNavItemGroup from './PressNavItemGroup.vue'
|
|
5
7
|
|
|
6
8
|
defineProps<{
|
|
7
9
|
isScreenOpen?: boolean
|
|
@@ -19,36 +21,38 @@ const themeConfig = useThemeConfig()
|
|
|
19
21
|
|
|
20
22
|
<template>
|
|
21
23
|
<div class="press-navbar flex justify-between items-center px-6 py-4" :class="{ 'has-sidebar': hasSidebar }">
|
|
22
|
-
<
|
|
24
|
+
<router-link class="text-xl" to="/" :aria-label="config.title">
|
|
23
25
|
<span class="md:inline">{{ config.title }}</span>
|
|
24
|
-
</
|
|
25
|
-
<div class="flex justify-center items-
|
|
26
|
-
<template v-for="
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
:href="item.link"
|
|
30
|
-
target="_blank"
|
|
31
|
-
rel="noopener"
|
|
32
|
-
>{{ item.text }}</a>
|
|
33
|
-
|
|
34
|
-
<span v-if="i !== themeConfig.nav.length - 1" class="mr-2 ml-2">·</span>
|
|
26
|
+
</router-link>
|
|
27
|
+
<div class="self-stretch flex justify-center items-center text-sm leading-5">
|
|
28
|
+
<template v-for="item in themeConfig.nav" :key="item.text">
|
|
29
|
+
<PressNavItemLink v-if="'link' in item" class="px-2" :item="item" />
|
|
30
|
+
<PressNavItemGroup v-else class="px-2" :item="item" />
|
|
35
31
|
</template>
|
|
36
|
-
|
|
37
|
-
<PressToggleLocale m="x-2" />
|
|
32
|
+
<PressToggleLocale p="x-2" />
|
|
38
33
|
<PressSwitchAppearance m="l-2" />
|
|
39
34
|
</div>
|
|
40
35
|
</div>
|
|
41
36
|
</template>
|
|
42
37
|
|
|
43
|
-
<style lang="scss"
|
|
38
|
+
<style lang="scss">
|
|
44
39
|
@use 'valaxy/client/styles/mixins' as *;
|
|
45
40
|
|
|
41
|
+
:root {
|
|
42
|
+
--pr-navbar-c-bg: rgba(255, 255, 255, 0.8);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.dark {
|
|
46
|
+
--pr-navbar-c-bg: rgba(24, 24, 24, 0.8);
|
|
47
|
+
}
|
|
48
|
+
|
|
46
49
|
.press-navbar {
|
|
47
50
|
position: relative;
|
|
48
51
|
border-bottom: 1px solid var(--pr-c-divider-light);
|
|
49
52
|
padding: 0 8px 0 24px;
|
|
50
53
|
height: var(--pr-nav-height);
|
|
51
|
-
transition: border-color 0.5s
|
|
54
|
+
transition: border-color 0.5s;
|
|
55
|
+
background-color: var(--pr-navbar-c-bg);
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
@include media('md') {
|
|
@@ -63,11 +67,6 @@ const themeConfig = useThemeConfig()
|
|
|
63
67
|
padding-right: 32px;
|
|
64
68
|
-webkit-backdrop-filter: saturate(50%) blur(8px);
|
|
65
69
|
backdrop-filter: saturate(50%) blur(8px);
|
|
66
|
-
background: rgba(255, 255, 255, 0.7);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.dark .press-navbar.has-sidebar .content {
|
|
70
|
-
background: rgba(36, 36, 36, 0.7);
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
@supports not (backdrop-filter: saturate(50%) blur(8px)) {
|
|
@@ -88,13 +87,6 @@ const themeConfig = useThemeConfig()
|
|
|
88
87
|
max-width: calc(var(--pr-layout-max-width) - 64px);
|
|
89
88
|
}
|
|
90
89
|
|
|
91
|
-
.content {
|
|
92
|
-
display: flex;
|
|
93
|
-
justify-content: flex-end;
|
|
94
|
-
align-items: center;
|
|
95
|
-
flex-grow: 1;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
90
|
.menu + .translations::before,
|
|
99
91
|
.menu + .appearance::before,
|
|
100
92
|
.menu + .social-links::before,
|
|
@@ -116,8 +108,4 @@ const themeConfig = useThemeConfig()
|
|
|
116
108
|
.appearance + .social-links::before {
|
|
117
109
|
margin-left: 16px;
|
|
118
110
|
}
|
|
119
|
-
|
|
120
|
-
.social-links {
|
|
121
|
-
margin-right: -8px;
|
|
122
|
-
}
|
|
123
111
|
</style>
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import type { NavItemGroup } from '../../types'
|
|
4
|
+
defineProps<{
|
|
5
|
+
item: NavItemGroup
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const open = ref(false)
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<div
|
|
13
|
+
ref="el"
|
|
14
|
+
class="flex self-stretch relative group"
|
|
15
|
+
:aria-expanded="open"
|
|
16
|
+
aria-haspopup="true"
|
|
17
|
+
@mouseenter="open = true"
|
|
18
|
+
@mouseleave="open = false"
|
|
19
|
+
>
|
|
20
|
+
<button
|
|
21
|
+
type="button"
|
|
22
|
+
class="button flex items-center"
|
|
23
|
+
@click="open = !open"
|
|
24
|
+
>
|
|
25
|
+
<span class="text">
|
|
26
|
+
{{ item.text }}
|
|
27
|
+
</span>
|
|
28
|
+
<div i-ri-arrow-drop-down-line />
|
|
29
|
+
</button>
|
|
30
|
+
|
|
31
|
+
<div class="menu grow" flex="~ col" items="start">
|
|
32
|
+
<AppLink v-for="itemLink in item.items" :key="itemLink.text" class="menu-item" p="x-3" :to="itemLink.link">
|
|
33
|
+
{{ itemLink.text }}
|
|
34
|
+
</AppLink>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<style lang="scss" scoped>
|
|
40
|
+
.group .button{
|
|
41
|
+
color: var(--pr-nav-text);
|
|
42
|
+
font-weight: 500;
|
|
43
|
+
font-size: 14px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.group[aria-expanded="true"] .button{
|
|
47
|
+
color: rgba(60, 60, 60, 0.70);
|
|
48
|
+
transition: color 0.25s;
|
|
49
|
+
|
|
50
|
+
.dark &{
|
|
51
|
+
color: rgba(235, 235, 235, 0.6)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.menu {
|
|
56
|
+
position: absolute;
|
|
57
|
+
left: 50%;
|
|
58
|
+
|
|
59
|
+
min-width: 128px;
|
|
60
|
+
opacity: 0;
|
|
61
|
+
visibility: hidden;
|
|
62
|
+
transition: opacity 0.25s, visibility 0.25s, transform 0.25s;
|
|
63
|
+
transform: translateX(-50%) translateY(calc(var(--pr-nav-height) / 2));
|
|
64
|
+
|
|
65
|
+
border-radius: 12px;
|
|
66
|
+
padding: 12px;
|
|
67
|
+
border: 1px solid rgba(60, 60, 60, 0.12);
|
|
68
|
+
background-color: #ffffff;
|
|
69
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.08);
|
|
70
|
+
.dark &{
|
|
71
|
+
background-color: #242424;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
&-item{
|
|
75
|
+
display: flex;
|
|
76
|
+
width: 100%;
|
|
77
|
+
border-radius: 6px;
|
|
78
|
+
color: var(--pr-nav-text);
|
|
79
|
+
line-height: 32px;
|
|
80
|
+
font-size: 14px;
|
|
81
|
+
font-weight: 500;
|
|
82
|
+
white-space: nowrap;
|
|
83
|
+
transition: background-color .25s,color .25s;
|
|
84
|
+
|
|
85
|
+
&:hover{
|
|
86
|
+
background-color: #f1f1f1;
|
|
87
|
+
color: var(--va-c-brand);
|
|
88
|
+
|
|
89
|
+
.dark &{
|
|
90
|
+
background-color: #2f2f2f;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.group[aria-expanded="true"] > .menu {
|
|
98
|
+
opacity: 1;
|
|
99
|
+
visibility: visible;
|
|
100
|
+
}
|
|
101
|
+
</style>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { useRoute } from 'vue-router'
|
|
3
|
+
import type { NavItemLink } from '../../types'
|
|
4
|
+
defineProps<{
|
|
5
|
+
item: NavItemLink
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const route = useRoute()
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<AppLink
|
|
13
|
+
class="press-nav-item-link"
|
|
14
|
+
:class="{
|
|
15
|
+
active: route.path === item.link,
|
|
16
|
+
}"
|
|
17
|
+
:to="item.link"
|
|
18
|
+
rel="noopener"
|
|
19
|
+
show-external-icon
|
|
20
|
+
>
|
|
21
|
+
{{ item.text }}
|
|
22
|
+
</AppLink>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<style lang="scss" scoped>
|
|
26
|
+
.press-nav-item-link{
|
|
27
|
+
font-size: 14px;
|
|
28
|
+
font-weight: 500;
|
|
29
|
+
color: var(--pr-nav-text);
|
|
30
|
+
transition: color 0.25s;
|
|
31
|
+
|
|
32
|
+
&:hover{
|
|
33
|
+
color: var(--va-c-brand);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
.active{
|
|
37
|
+
color: var(--va-c-brand);
|
|
38
|
+
}
|
|
39
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useData } from 'valaxy'
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useThemeConfig } from '.'
|
|
4
|
+
|
|
5
|
+
export function useEditLink() {
|
|
6
|
+
const themeConfig = useThemeConfig()
|
|
7
|
+
return computed(() => {
|
|
8
|
+
const { text = 'Edit this page', pattern } = themeConfig.value.editLink || {}
|
|
9
|
+
const { relativePath } = useData()
|
|
10
|
+
const url = pattern.replace(/:path/g, relativePath)
|
|
11
|
+
|
|
12
|
+
return { url, text }
|
|
13
|
+
})
|
|
14
|
+
}
|
package/composables/index.ts
CHANGED
package/config/index.ts
CHANGED
|
@@ -12,7 +12,13 @@ export const defaultThemeConfig: ThemeConfig = {
|
|
|
12
12
|
primary: '#0078E7',
|
|
13
13
|
},
|
|
14
14
|
|
|
15
|
+
sidebar: [],
|
|
15
16
|
nav: [],
|
|
16
|
-
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
editLink: {
|
|
19
|
+
pattern: 'https://github.com/YunYouJun/valaxy/edit/main/docs/:path',
|
|
20
|
+
text: 'Edit this page on GitHub',
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
footer: {},
|
|
24
|
+
}
|
package/layouts/layout.vue
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { useSidebar } from 'valaxy
|
|
2
|
+
import { useLayout, useSidebar } from 'valaxy'
|
|
3
3
|
|
|
4
4
|
const { isOpen: isSidebarOpen, open: openSidebar, close: closeSidebar } = useSidebar()
|
|
5
|
+
const layout = useLayout()
|
|
5
6
|
</script>
|
|
6
7
|
|
|
7
8
|
<template>
|
|
@@ -9,7 +10,7 @@ const { isOpen: isSidebarOpen, open: openSidebar, close: closeSidebar } = useSid
|
|
|
9
10
|
<PressNav />
|
|
10
11
|
<PressLocalNav :open="isSidebarOpen" @open-menu="openSidebar()" />
|
|
11
12
|
<slot name="sidebar">
|
|
12
|
-
<PressSidebar :open="isSidebarOpen" />
|
|
13
|
+
<PressSidebar v-if="layout !== 'post'" :open="isSidebarOpen" />
|
|
13
14
|
</slot>
|
|
14
15
|
<PressBackdrop :show="isSidebarOpen" @click="closeSidebar" />
|
|
15
16
|
|
|
@@ -50,6 +51,8 @@ const { isOpen: isSidebarOpen, open: openSidebar, close: closeSidebar } = useSid
|
|
|
50
51
|
</component>
|
|
51
52
|
</router-view>
|
|
52
53
|
</slot>
|
|
54
|
+
|
|
55
|
+
<PressFooter />
|
|
53
56
|
</div>
|
|
54
57
|
</template>
|
|
55
58
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "valaxy-theme-press",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Docs Theme for Valaxy",
|
|
5
5
|
"author": {
|
|
6
6
|
"email": "me@yunyoujun.cn",
|
|
@@ -19,10 +19,20 @@
|
|
|
19
19
|
"main": "node/index.ts",
|
|
20
20
|
"types": "types/index.d.ts",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@docsearch/css": "^3.
|
|
23
|
-
"@docsearch/js": "^3.
|
|
22
|
+
"@docsearch/css": "^3.3.0",
|
|
23
|
+
"@docsearch/js": "^3.3.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"valaxy": "
|
|
26
|
+
"valaxy": "workspace:*"
|
|
27
|
+
},
|
|
28
|
+
"pnpm": {
|
|
29
|
+
"peerDependencyRules": {
|
|
30
|
+
"ignoreMissing": [
|
|
31
|
+
"@algolia/client-search",
|
|
32
|
+
"@types/react",
|
|
33
|
+
"react",
|
|
34
|
+
"react-dom"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
27
37
|
}
|
|
28
|
-
}
|
|
38
|
+
}
|
package/setup/main.ts
CHANGED
|
@@ -58,11 +58,10 @@ export default defineAppSetup((ctx) => {
|
|
|
58
58
|
|
|
59
59
|
function scrollTo(el: HTMLElement, hash: string, smooth = false) {
|
|
60
60
|
let target: Element | null = null
|
|
61
|
-
|
|
62
61
|
try {
|
|
63
62
|
target = el.classList.contains('header-anchor')
|
|
64
63
|
? el
|
|
65
|
-
: document.querySelector(decodeURIComponent(hash))
|
|
64
|
+
: (decodeURIComponent(hash) && document.querySelector(decodeURIComponent(hash))) || null
|
|
66
65
|
}
|
|
67
66
|
catch (e) {
|
|
68
67
|
console.warn(e)
|
package/styles/css-vars.scss
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
:root {
|
|
6
6
|
--pr-c-text-code: #374562;
|
|
7
|
+
--pr-c-text-1: #213547;
|
|
7
8
|
|
|
8
9
|
// aside
|
|
9
|
-
--pr-aside-text-1:
|
|
10
|
-
--pr-aside-text-2:
|
|
10
|
+
--pr-aside-text-1: var(--pr-c-text-1);
|
|
11
|
+
--pr-aside-text-2: rgba(60, 60, 60, 0.702);
|
|
11
12
|
|
|
12
13
|
--pr-aside-divider: rgba(60, 60, 60, 0.122);
|
|
13
14
|
|
|
@@ -16,13 +17,15 @@
|
|
|
16
17
|
// nav
|
|
17
18
|
--pr-nav-height: var(--pr-nav-height-mobile);
|
|
18
19
|
--pr-nav-height-mobile: 60px;
|
|
20
|
+
--pr-nav-text: var(--pr-c-text-1);
|
|
19
21
|
|
|
20
22
|
// z-index
|
|
21
23
|
--va-z-overlay: var(--pr-z-index-backdrop);
|
|
22
|
-
--pr-z-index-nav: 8;
|
|
23
|
-
--pr-z-index-
|
|
24
|
+
--pr-z-index-local-nav: 8;
|
|
25
|
+
--pr-z-index-nav: 9;
|
|
24
26
|
--pr-z-index-backdrop: 10;
|
|
25
|
-
--pr-z-index-
|
|
27
|
+
--pr-z-index-aside: 11;
|
|
28
|
+
--pr-z-index-sidebar: 12;
|
|
26
29
|
|
|
27
30
|
// switch
|
|
28
31
|
--pr-switch-divider: rgba(60, 60, 60, 0.29);
|
|
@@ -31,9 +34,9 @@
|
|
|
31
34
|
|
|
32
35
|
.dark {
|
|
33
36
|
--pr-c-text-code: var(--pr-c-indigo-lighter);
|
|
37
|
+
--pr-c-text-1: #ffffffde;
|
|
34
38
|
|
|
35
39
|
// aside
|
|
36
|
-
--pr-aside-text-1: #ffffffde;
|
|
37
40
|
--pr-aside-text-2: #ebebeb99;
|
|
38
41
|
--pr-aside-divider: rgba(84, 84, 84, 0.48);
|
|
39
42
|
|
package/styles/helper.scss
CHANGED
|
@@ -28,17 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
border-radius: 50%;
|
|
30
30
|
|
|
31
|
-
transition: background-color var(--va-transition-duration);
|
|
32
|
-
|
|
33
31
|
div {
|
|
34
32
|
font-size: 1.2rem;
|
|
35
33
|
}
|
|
36
|
-
|
|
37
|
-
&:hover {
|
|
38
|
-
background-color: rgba(var(--va-c-primary-rgb), 0.08);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
&:active {
|
|
42
|
-
background-color: rgba(var(--va-c-primary-rgb), 0.16);
|
|
43
|
-
}
|
|
44
34
|
}
|
package/styles/markdown.scss
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
a {
|
|
16
|
+
display: inline-block;
|
|
16
17
|
text-decoration: none;
|
|
17
18
|
border-bottom: 1px solid transparent;
|
|
18
19
|
transition: all 0.4s;
|
|
@@ -28,6 +29,14 @@
|
|
|
28
29
|
padding: 3px 6px;
|
|
29
30
|
border-radius: 4px;
|
|
30
31
|
font-weight: 500;
|
|
32
|
+
|
|
33
|
+
&::before {
|
|
34
|
+
content: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&::after {
|
|
38
|
+
content: none;
|
|
39
|
+
}
|
|
31
40
|
}
|
|
32
41
|
}
|
|
33
42
|
|
|
@@ -37,4 +46,4 @@
|
|
|
37
46
|
margin: 0 -1.5rem;
|
|
38
47
|
}
|
|
39
48
|
}
|
|
40
|
-
}
|
|
49
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,33 +1,71 @@
|
|
|
1
1
|
export * from '../composables'
|
|
2
2
|
export * from './home.d'
|
|
3
3
|
|
|
4
|
-
export namespace
|
|
5
|
-
export type Config = ThemeConfig
|
|
4
|
+
export namespace PressTheme {
|
|
6
5
|
export type Sidebar = any
|
|
7
|
-
}
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
export interface Footer {
|
|
8
|
+
message?: string;
|
|
9
|
+
copyright?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface EditLink {
|
|
13
|
+
/**
|
|
14
|
+
* Pattern for edit link.
|
|
15
|
+
*
|
|
16
|
+
* @example 'https://github.com/YunYouJun/valaxy/edit/main/docs/:path'
|
|
17
|
+
*/
|
|
18
|
+
pattern: string
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Custom text for edit link.
|
|
22
|
+
*
|
|
23
|
+
* @default 'Edit this page'
|
|
24
|
+
*/
|
|
25
|
+
text?: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface Config {
|
|
20
29
|
/**
|
|
21
|
-
*
|
|
22
|
-
* @default '
|
|
30
|
+
* toc title
|
|
31
|
+
* @default 'On this page'
|
|
23
32
|
*/
|
|
24
|
-
|
|
33
|
+
outlineTitle: string
|
|
34
|
+
|
|
35
|
+
colors: {
|
|
36
|
+
/**
|
|
37
|
+
* primary color
|
|
38
|
+
* @default '#0078E7'
|
|
39
|
+
*/
|
|
40
|
+
primary: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
nav: Array<NavItem>
|
|
44
|
+
sidebar: string[]
|
|
45
|
+
|
|
46
|
+
editLink: EditLink
|
|
47
|
+
|
|
48
|
+
footer: Footer
|
|
25
49
|
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface NavItemLink {
|
|
53
|
+
link: string
|
|
54
|
+
text: string
|
|
55
|
+
active?: string
|
|
56
|
+
}
|
|
26
57
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}[]
|
|
58
|
+
export interface NavItemGroup {
|
|
59
|
+
text: string
|
|
60
|
+
items: NavItemLink[]
|
|
31
61
|
}
|
|
32
62
|
|
|
63
|
+
export type NavItem = NavItemLink | NavItemGroup
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Theme Config
|
|
69
|
+
*/
|
|
70
|
+
export type ThemeConfig = PressTheme.Config
|
|
33
71
|
export type ThemeUserConfig = Partial<ThemeConfig>
|
package/valaxy.config.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ResolvedValaxyOptions } from 'valaxy'
|
|
2
2
|
import { defineTheme } from 'valaxy'
|
|
3
3
|
import type { Plugin } from 'vite'
|
|
4
|
+
import { defaultThemeConfig } from './config'
|
|
4
5
|
import type { ThemeConfig } from './types'
|
|
5
6
|
|
|
6
7
|
function ThemeVitePlugin(options: ResolvedValaxyOptions<ThemeConfig>): Plugin {
|
|
@@ -29,6 +30,7 @@ function ThemeVitePlugin(options: ResolvedValaxyOptions<ThemeConfig>): Plugin {
|
|
|
29
30
|
|
|
30
31
|
export default defineTheme<ThemeConfig>((options) => {
|
|
31
32
|
return {
|
|
33
|
+
themeConfig: defaultThemeConfig,
|
|
32
34
|
vite: {
|
|
33
35
|
plugins: [ThemeVitePlugin(options)],
|
|
34
36
|
},
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2022 云游君 YunYouJun <me@yunyoujun.cn>
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|