vitepress 1.0.0-draft.1 → 1.0.0-draft.2
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/dist/client/index.d.ts +5 -0
- package/dist/client/shared.js +1 -0
- package/dist/client/theme-default/Layout.vue +18 -1
- package/dist/client/theme-default/components/VPBackdrop.vue +1 -1
- package/dist/client/theme-default/components/VPBox.vue +59 -0
- package/dist/client/theme-default/components/VPButton.vue +123 -0
- package/dist/client/theme-default/components/VPContent.vue +35 -5
- package/dist/client/theme-default/components/{VPContentDoc.vue → VPDoc.vue} +13 -13
- package/dist/client/theme-default/components/{VPContentDocFooter.vue → VPDocFooter.vue} +3 -2
- package/dist/client/theme-default/components/{VPContentDocOutline.vue → VPDocOutline.vue} +2 -2
- package/dist/client/theme-default/components/VPFooter.vue +53 -0
- package/dist/client/theme-default/components/VPHero.vue +144 -0
- package/dist/client/theme-default/components/VPHome.vue +33 -0
- package/dist/client/theme-default/components/VPHomeFeatures.vue +96 -0
- package/dist/client/theme-default/components/VPHomeHero.vue +17 -0
- package/dist/client/theme-default/components/VPHomeSponsors.vue +97 -0
- package/dist/client/theme-default/components/VPNavBar.vue +1 -0
- package/dist/client/theme-default/components/VPNavBarAppearance.vue +4 -1
- package/dist/client/theme-default/components/VPNavBarExtra.vue +2 -2
- package/dist/client/theme-default/components/VPNavBarSearch.vue +3 -3
- package/dist/client/theme-default/components/VPNavBarTitle.vue +26 -13
- package/dist/client/theme-default/components/VPNavScreenAppearance.vue +4 -1
- package/dist/client/theme-default/components/VPPage.vue +5 -0
- package/dist/client/theme-default/components/VPSponsors.vue +77 -0
- package/dist/client/theme-default/components/VPSponsorsGrid.vue +32 -0
- package/dist/client/theme-default/components/VPSwitchAppearance.vue +3 -3
- package/dist/client/theme-default/components/icons/VPIconHeart.vue +5 -0
- package/dist/client/theme-default/composables/outline.js +1 -19
- package/dist/client/theme-default/composables/sponsor-grid.js +92 -0
- package/dist/client/theme-default/composables/sponsor.js +87 -0
- package/dist/client/theme-default/index.js +4 -0
- package/dist/client/theme-default/styles/base.css +3 -0
- package/dist/client/theme-default/styles/vars.css +86 -1
- package/dist/client/theme-default/styles/vp-doc.css +8 -2
- package/dist/client/theme-default/styles/vp-sponsor.css +86 -0
- package/dist/client/theme-default/support/utils.js +19 -0
- package/dist/node/alias.js +60 -0
- package/dist/node/alias.js.map +1 -0
- package/dist/node/build/build.js +57 -0
- package/dist/node/build/build.js.map +1 -0
- package/dist/node/build/buildMPAClient.js +44 -0
- package/dist/node/build/buildMPAClient.js.map +1 -0
- package/dist/node/build/bundle.js +163 -0
- package/dist/node/build/bundle.js.map +1 -0
- package/dist/node/build/render.js +185 -0
- package/dist/node/build/render.js.map +1 -0
- package/dist/node/cli.js +37 -294
- package/dist/node/cli.js.map +1 -0
- package/dist/node/config.js +176 -0
- package/dist/node/config.js.map +1 -0
- package/dist/node/index.d.ts +19 -1
- package/dist/node/index.js +22 -37
- package/dist/node/index.js.map +1 -0
- package/dist/node/markdown/markdown.js +75 -0
- package/dist/node/markdown/markdown.js.map +1 -0
- package/dist/node/markdown/plugins/component.js +86 -0
- package/dist/node/markdown/plugins/component.js.map +1 -0
- package/dist/node/markdown/plugins/containers.js +41 -0
- package/dist/node/markdown/plugins/containers.js.map +1 -0
- package/dist/node/markdown/plugins/headings.js +25 -0
- package/dist/node/markdown/plugins/headings.js.map +1 -0
- package/dist/node/markdown/plugins/highlight.js +53 -0
- package/dist/node/markdown/plugins/highlight.js.map +1 -0
- package/dist/node/markdown/plugins/highlightLines.js +48 -0
- package/dist/node/markdown/plugins/highlightLines.js.map +1 -0
- package/dist/node/markdown/plugins/hoist.js +22 -0
- package/dist/node/markdown/plugins/hoist.js.map +1 -0
- package/dist/node/markdown/plugins/image.js +17 -0
- package/dist/node/markdown/plugins/image.js.map +1 -0
- package/dist/node/markdown/plugins/lineNumbers.js +23 -0
- package/dist/node/markdown/plugins/lineNumbers.js.map +1 -0
- package/dist/node/markdown/plugins/link.js +85 -0
- package/dist/node/markdown/plugins/link.js.map +1 -0
- package/dist/node/markdown/plugins/preWrapper.js +22 -0
- package/dist/node/markdown/plugins/preWrapper.js.map +1 -0
- package/dist/node/markdown/plugins/slugify.js +26 -0
- package/dist/node/markdown/plugins/slugify.js.map +1 -0
- package/dist/node/markdown/plugins/snippet.js +146 -0
- package/dist/node/markdown/plugins/snippet.js.map +1 -0
- package/dist/node/markdownToVue.js +166 -0
- package/dist/node/markdownToVue.js.map +1 -0
- package/dist/node/plugin.js +227 -0
- package/dist/node/plugin.js.map +1 -0
- package/dist/node/serve/serve.js +59 -0
- package/dist/node/serve/serve.js.map +1 -0
- package/dist/node/{serve-428d4610.js → serve-b5dc02b2.js} +26 -2
- package/dist/node/server.js +18 -0
- package/dist/node/server.js.map +1 -0
- package/dist/node/shared.js +72 -0
- package/dist/node/shared.js.map +1 -0
- package/dist/node/staticDataPlugin.js +99 -0
- package/dist/node/staticDataPlugin.js.map +1 -0
- package/dist/node/utils/getGitTimestamp.js +17 -0
- package/dist/node/utils/getGitTimestamp.js.map +1 -0
- package/dist/node/utils/parseHeader.js +57 -0
- package/dist/node/utils/parseHeader.js.map +1 -0
- package/dist/node/utils/slash.js +8 -0
- package/dist/node/utils/slash.js.map +1 -0
- package/package.json +4 -2
- package/types/default-theme.d.ts +12 -0
- package/types/shared.d.ts +11 -6
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useData } from 'vitepress'
|
|
4
|
+
import VPBox from './VPBox.vue'
|
|
5
|
+
|
|
6
|
+
const { frontmatter: fm } = useData()
|
|
7
|
+
|
|
8
|
+
const grid = computed(() => {
|
|
9
|
+
const length = fm.value.features?.length
|
|
10
|
+
|
|
11
|
+
if (!length) {
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (length === 2) {
|
|
16
|
+
return 'grid-2'
|
|
17
|
+
} else if (length === 3) {
|
|
18
|
+
return 'grid-3'
|
|
19
|
+
} else if (length % 3 === 0) {
|
|
20
|
+
return 'grid-6'
|
|
21
|
+
} else if (length % 2 === 0) {
|
|
22
|
+
return 'grid-4'
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<div v-if="fm.features" class="VPHomeFeatures">
|
|
29
|
+
<div class="container">
|
|
30
|
+
<div class="items">
|
|
31
|
+
<div v-for="feature in fm.features" :key="feature.title" class="item" :class="[grid]">
|
|
32
|
+
<VPBox
|
|
33
|
+
:icon="feature.icon"
|
|
34
|
+
:title="feature.title"
|
|
35
|
+
:details="feature.details"
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<style scoped>
|
|
44
|
+
.VPHomeFeatures {
|
|
45
|
+
padding: 0 24px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@media (min-width: 640px) {
|
|
49
|
+
.VPHomeFeatures {
|
|
50
|
+
padding: 0 48px;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.container {
|
|
55
|
+
margin: 0 auto;
|
|
56
|
+
max-width: 960px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.items {
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-wrap: wrap;
|
|
62
|
+
margin: -8px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.item {
|
|
66
|
+
padding: 8px;
|
|
67
|
+
width: 100%;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@media (min-width: 640px) {
|
|
71
|
+
.item.grid-2,
|
|
72
|
+
.item.grid-4,
|
|
73
|
+
.item.grid-6 {
|
|
74
|
+
width: calc(100% / 2);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@media (min-width: 768px) {
|
|
79
|
+
.item.grid-2,
|
|
80
|
+
.item.grid-4 {
|
|
81
|
+
width: calc(100% / 2);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.item.grid-3,
|
|
85
|
+
.item.grid-6 {
|
|
86
|
+
width: calc(100% / 3);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@media (min-width: 960px) {
|
|
91
|
+
.item.grid-4 {
|
|
92
|
+
width: calc(100% / 4);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useData } from 'vitepress'
|
|
3
|
+
import VPHero from './VPHero.vue'
|
|
4
|
+
|
|
5
|
+
const { frontmatter: fm } = useData()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<div v-if="fm.hero" class="VPHomeHero">
|
|
10
|
+
<VPHero
|
|
11
|
+
:name="fm.hero.name"
|
|
12
|
+
:text="fm.hero.text"
|
|
13
|
+
:tagline="fm.hero.tagline"
|
|
14
|
+
:actions="fm.hero.actions"
|
|
15
|
+
/>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import VPIconHeart from './icons/VPIconHeart.vue'
|
|
3
|
+
import VPButton from './VPButton.vue'
|
|
4
|
+
import VPSponsors from './VPSponsors.vue'
|
|
5
|
+
|
|
6
|
+
interface Sponsors {
|
|
7
|
+
tier: string
|
|
8
|
+
size?: 'medium' | 'big'
|
|
9
|
+
items: Sponsor[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface Sponsor {
|
|
13
|
+
name: string
|
|
14
|
+
img: string
|
|
15
|
+
url: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
defineProps<{
|
|
19
|
+
message?: string
|
|
20
|
+
actionText?: string
|
|
21
|
+
actionLink?: string
|
|
22
|
+
data: Sponsors[]
|
|
23
|
+
}>()
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<section class="VPHomeSponsors">
|
|
28
|
+
<div class="container">
|
|
29
|
+
<div class="header">
|
|
30
|
+
<div class="love"><VPIconHeart class="icon" /></div>
|
|
31
|
+
<h2 v-if="message" class="message">{{ message }}</h2>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="sponsors">
|
|
35
|
+
<VPSponsors :data="data" />
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div v-if="actionLink" class="action">
|
|
39
|
+
<VPButton
|
|
40
|
+
theme="sponsor"
|
|
41
|
+
:text="actionText ?? 'Become a sponsor'"
|
|
42
|
+
:href="actionLink"
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</section>
|
|
47
|
+
</template>
|
|
48
|
+
|
|
49
|
+
<style scoped>
|
|
50
|
+
.VPHomeSponsors {
|
|
51
|
+
border-top: 1px solid var(--vp-c-divider-light);
|
|
52
|
+
padding: 88px 24px 96px;
|
|
53
|
+
background-color: var(--vp-c-bg-content);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.container {
|
|
57
|
+
margin: 0 auto;
|
|
58
|
+
max-width: 960px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.love {
|
|
62
|
+
margin: 0 auto;
|
|
63
|
+
width: 28px;
|
|
64
|
+
height: 28px;
|
|
65
|
+
color: var(--vp-c-text-3);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.icon {
|
|
69
|
+
width: 28px;
|
|
70
|
+
height: 28px;
|
|
71
|
+
fill: currentColor;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.message {
|
|
75
|
+
margin: 0 auto;
|
|
76
|
+
padding-top: 10px;
|
|
77
|
+
max-width: 320px;
|
|
78
|
+
text-align: center;
|
|
79
|
+
line-height: 24px;
|
|
80
|
+
font-size: 16px;
|
|
81
|
+
font-weight: 500;
|
|
82
|
+
color: var(--vp-c-text-2);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.sponsors {
|
|
86
|
+
padding-top: 32px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.sponsor + .sponsor {
|
|
90
|
+
padding-top: 0px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.action {
|
|
94
|
+
padding-top: 40px;
|
|
95
|
+
text-align: center;
|
|
96
|
+
}
|
|
97
|
+
</style>
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import { useData } from 'vitepress'
|
|
2
3
|
import VPSwitchAppearance from './VPSwitchAppearance.vue'
|
|
4
|
+
|
|
5
|
+
const { site } = useData()
|
|
3
6
|
</script>
|
|
4
7
|
|
|
5
8
|
<template>
|
|
6
|
-
<div class="VPNavBarAppearance">
|
|
9
|
+
<div v-if="site.appearance" class="VPNavBarAppearance">
|
|
7
10
|
<VPSwitchAppearance />
|
|
8
11
|
</div>
|
|
9
12
|
</template>
|
|
@@ -4,7 +4,7 @@ import VPFlyout from './VPFlyout.vue'
|
|
|
4
4
|
import VPSwitchAppearance from './VPSwitchAppearance.vue'
|
|
5
5
|
import VPSocialLinks from './VPSocialLinks.vue'
|
|
6
6
|
|
|
7
|
-
const { theme } = useData()
|
|
7
|
+
const { site, theme } = useData()
|
|
8
8
|
</script>
|
|
9
9
|
|
|
10
10
|
<template>
|
|
@@ -23,7 +23,7 @@ const { theme } = useData()
|
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
25
25
|
|
|
26
|
-
<div class="group">
|
|
26
|
+
<div v-if="site.appearance" class="group">
|
|
27
27
|
<div class="item">
|
|
28
28
|
<p class="label">Appearance</p>
|
|
29
29
|
<div class="appearance-action">
|
|
@@ -3,9 +3,9 @@ import '@docsearch/css'
|
|
|
3
3
|
import { useData } from 'vitepress'
|
|
4
4
|
import { defineAsyncComponent, ref, onMounted, onUnmounted } from 'vue'
|
|
5
5
|
|
|
6
|
-
const VPAlgoliaSearchBox = defineAsyncComponent(
|
|
7
|
-
|
|
8
|
-
)
|
|
6
|
+
const VPAlgoliaSearchBox = defineAsyncComponent(() => {
|
|
7
|
+
return import('./VPAlgoliaSearchBox.vue')
|
|
8
|
+
})
|
|
9
9
|
|
|
10
10
|
const { theme } = useData()
|
|
11
11
|
|
|
@@ -1,39 +1,52 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useData } from 'vitepress'
|
|
3
|
+
import { useSidebar } from '../composables/sidebar'
|
|
3
4
|
|
|
4
5
|
const { site, theme } = useData()
|
|
6
|
+
const { hasSidebar } = useSidebar()
|
|
5
7
|
</script>
|
|
6
8
|
|
|
7
9
|
<template>
|
|
8
|
-
<
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
<div class="VPNavBarTitle" :class="{ 'has-sidebar': hasSidebar }">
|
|
11
|
+
<a class="title" href="/">
|
|
12
|
+
<img v-if="theme.logo" class="logo" :src="theme.logo" :alt="site.title">
|
|
13
|
+
{{ site.title }}
|
|
14
|
+
</a>
|
|
15
|
+
</div>
|
|
12
16
|
</template>
|
|
13
17
|
|
|
14
18
|
<style scoped>
|
|
15
19
|
.VPNavBarTitle {
|
|
20
|
+
flex-shrink: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@media (min-width: 960px) {
|
|
24
|
+
.VPNavBarTitle.has-sidebar {
|
|
25
|
+
margin-right: 32px;
|
|
26
|
+
width: calc(var(--vp-sidebar-width) - 64px);
|
|
27
|
+
border-bottom: 1px solid var(--vp-c-divider-light);
|
|
28
|
+
background-color: var(--vp-c-bg-sidebar);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.title {
|
|
16
33
|
display: flex;
|
|
17
34
|
align-items: center;
|
|
18
|
-
|
|
35
|
+
width: 100%;
|
|
36
|
+
height: var(--vp-nav-height);
|
|
19
37
|
font-size: 16px;
|
|
20
38
|
font-weight: 600;
|
|
21
39
|
color: var(--vp-c-text-1);
|
|
22
|
-
transition:
|
|
40
|
+
transition: opacity 0.25s;
|
|
23
41
|
}
|
|
24
42
|
|
|
25
|
-
.
|
|
43
|
+
.title:hover {
|
|
26
44
|
opacity: 0.6;
|
|
27
45
|
}
|
|
28
46
|
|
|
29
47
|
@media (min-width: 960px) {
|
|
30
|
-
.
|
|
48
|
+
.title {
|
|
31
49
|
flex-shrink: 0;
|
|
32
|
-
margin-right: 32px;
|
|
33
|
-
border-bottom: 1px solid var(--vp-c-divider-light);
|
|
34
|
-
width: calc(var(--vp-sidebar-width) - 64px);
|
|
35
|
-
height: var(--vp-nav-height-desktop);
|
|
36
|
-
background-color: var(--vp-c-bg-sidebar);
|
|
37
50
|
}
|
|
38
51
|
}
|
|
39
52
|
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import { useData } from 'vitepress'
|
|
2
3
|
import VPSwitchAppearance from './VPSwitchAppearance.vue'
|
|
4
|
+
|
|
5
|
+
const { site } = useData()
|
|
3
6
|
</script>
|
|
4
7
|
|
|
5
8
|
<template>
|
|
6
|
-
<div class="VPNavScreenAppearance">
|
|
9
|
+
<div v-if="site.appearance" class="VPNavScreenAppearance">
|
|
7
10
|
<p class="text">Appearance</p>
|
|
8
11
|
<VPSwitchAppearance />
|
|
9
12
|
</div>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import VPSponsorsGrid from './VPSponsorsGrid.vue'
|
|
4
|
+
|
|
5
|
+
interface Sponsors {
|
|
6
|
+
tier?: string
|
|
7
|
+
size?: 'small' | 'medium' | 'big'
|
|
8
|
+
items: Sponsor[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Sponsor {
|
|
12
|
+
name: string
|
|
13
|
+
img: string
|
|
14
|
+
url: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const props = defineProps<{
|
|
18
|
+
tier?: string
|
|
19
|
+
size?: 'small' | 'medium' | 'big'
|
|
20
|
+
data: Sposors[] | Sponsor[]
|
|
21
|
+
}>()
|
|
22
|
+
|
|
23
|
+
const sponsors = computed(() => {
|
|
24
|
+
const isSponsors = props.data.some((s: any) => s.items)
|
|
25
|
+
|
|
26
|
+
if (isSponsors) {
|
|
27
|
+
return props.data
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return [{
|
|
31
|
+
tier: props.tier,
|
|
32
|
+
size: props.size,
|
|
33
|
+
items: props.data
|
|
34
|
+
}]
|
|
35
|
+
})
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<div class="VPSponsors">
|
|
40
|
+
<section v-for="(sponsor, index) in sponsors" :key="index" class="section">
|
|
41
|
+
<h3 v-if="sponsor.tier" class="tier">{{ sponsor.tier }}</h3>
|
|
42
|
+
<VPSponsorsGrid :size="sponsor.size" :data="sponsor.items" />
|
|
43
|
+
</section>
|
|
44
|
+
</div>
|
|
45
|
+
</template>
|
|
46
|
+
|
|
47
|
+
<style scoped>
|
|
48
|
+
.VPSponsors {
|
|
49
|
+
border-radius: 16px;
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.section + .section {
|
|
54
|
+
margin-top: 4px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.tier {
|
|
58
|
+
margin-bottom: 4px;
|
|
59
|
+
padding: 13px 0 11px;
|
|
60
|
+
text-align: center;
|
|
61
|
+
letter-spacing: 1px;
|
|
62
|
+
line-height: 24px;
|
|
63
|
+
width: 100%;
|
|
64
|
+
font-size: 14px;
|
|
65
|
+
font-weight: 600;
|
|
66
|
+
color: var(--vp-c-text-2);
|
|
67
|
+
background-color: var(--vp-c-white-soft);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.dark .tier {
|
|
71
|
+
background-color: var(--vp-c-black-mute);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.VPSponsorsGrid + .tier {
|
|
75
|
+
margin-top: 4px;
|
|
76
|
+
}
|
|
77
|
+
</style>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import { useSponsorsGrid } from '../composables/sponsor-grid'
|
|
4
|
+
|
|
5
|
+
interface Sponsor {
|
|
6
|
+
name: string
|
|
7
|
+
img: string
|
|
8
|
+
url: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const props = defineProps<{
|
|
12
|
+
size?: 'small' | 'medium' | 'big'
|
|
13
|
+
data: Sponsor[]
|
|
14
|
+
}>()
|
|
15
|
+
|
|
16
|
+
const el = ref(null)
|
|
17
|
+
|
|
18
|
+
useSponsorsGrid({ el, size: props.size })
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<div class="VPSponsorsGrid vp-sponsor-grid" :class="[props.size ?? 'medium']" ref="el">
|
|
23
|
+
<div v-for="sponsor in data" :key="sponsor.tier" class="vp-sponsor-grid-item">
|
|
24
|
+
<a class="vp-sponsor-grid-link" :href="sponsor.url" target="_blank" rel="sponsored noopener">
|
|
25
|
+
<article class="vp-sponsor-grid-box">
|
|
26
|
+
<h4 class="visually-hidden">{{ sponsor.name }}</h4>
|
|
27
|
+
<img class="vp-sponsor-grid-image" :src="sponsor.img" :alt="sponsor.name" />
|
|
28
|
+
</article>
|
|
29
|
+
</a>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import { APPEARANCE_KEY } from '../../shared'
|
|
2
3
|
import VPSwitch from './VPSwitch.vue'
|
|
3
4
|
import VPIconSun from './icons/VPIconSun.vue'
|
|
4
5
|
import VPIconMoon from './icons/VPIconMoon.vue'
|
|
@@ -6,11 +7,10 @@ import VPIconMoon from './icons/VPIconMoon.vue'
|
|
|
6
7
|
const toggle = typeof localStorage !== 'undefined' ? useAppearance() : () => {}
|
|
7
8
|
|
|
8
9
|
function useAppearance() {
|
|
9
|
-
const storageKey = 'vitepress-theme-appearance'
|
|
10
10
|
const query = window.matchMedia('(prefers-color-scheme: dark)')
|
|
11
11
|
const classList = document.documentElement.classList
|
|
12
12
|
|
|
13
|
-
let userPreference = localStorage.getItem(
|
|
13
|
+
let userPreference = localStorage.getItem(APPEARANCE_KEY) || 'auto'
|
|
14
14
|
|
|
15
15
|
let isDark = userPreference === 'auto'
|
|
16
16
|
? query.matches
|
|
@@ -29,7 +29,7 @@ function useAppearance() {
|
|
|
29
29
|
? query.matches ? 'auto' : 'dark'
|
|
30
30
|
: query.matches ? 'light' : 'auto'
|
|
31
31
|
|
|
32
|
-
localStorage.setItem(
|
|
32
|
+
localStorage.setItem(APPEARANCE_KEY, userPreference)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function setClass(dark: boolean): void {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
3
|
+
<path d="M12,22.2c-0.3,0-0.5-0.1-0.7-0.3l-8.8-8.8c-2.5-2.5-2.5-6.7,0-9.2c2.5-2.5,6.7-2.5,9.2,0L12,4.3l0.4-0.4c0,0,0,0,0,0C13.6,2.7,15.2,2,16.9,2c0,0,0,0,0,0c1.7,0,3.4,0.7,4.6,1.9l0,0c1.2,1.2,1.9,2.9,1.9,4.6c0,1.7-0.7,3.4-1.9,4.6l-8.8,8.8C12.5,22.1,12.3,22.2,12,22.2zM7,4C5.9,4,4.7,4.4,3.9,5.3c-1.8,1.8-1.8,4.6,0,6.4l8.1,8.1l8.1-8.1c0.9-0.9,1.3-2,1.3-3.2c0-1.2-0.5-2.3-1.3-3.2l0,0C19.3,4.5,18.2,4,17,4c0,0,0,0,0,0c-1.2,0-2.3,0.5-3.2,1.3c0,0,0,0,0,0l-1.1,1.1c-0.4,0.4-1,0.4-1.4,0l-1.1-1.1C9.4,4.4,8.2,4,7,4z" />
|
|
4
|
+
</svg>
|
|
5
|
+
</template>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { onMounted, onUpdated, onUnmounted } from 'vue';
|
|
2
2
|
import { useMediaQuery } from '@vueuse/core';
|
|
3
|
+
import { throttleAndDebounce } from '../support/utils';
|
|
3
4
|
// magic number to avoid repeated retrieval
|
|
4
5
|
const PAGE_OFFSET = 56;
|
|
5
6
|
export function resolveHeaders(headers) {
|
|
@@ -109,22 +110,3 @@ function isAnchorActive(index, anchor, nextAnchor) {
|
|
|
109
110
|
}
|
|
110
111
|
return [false, null];
|
|
111
112
|
}
|
|
112
|
-
function throttleAndDebounce(fn, delay) {
|
|
113
|
-
let timeout;
|
|
114
|
-
let called = false;
|
|
115
|
-
return () => {
|
|
116
|
-
if (timeout) {
|
|
117
|
-
clearTimeout(timeout);
|
|
118
|
-
}
|
|
119
|
-
if (!called) {
|
|
120
|
-
fn();
|
|
121
|
-
called = true;
|
|
122
|
-
setTimeout(() => {
|
|
123
|
-
called = false;
|
|
124
|
-
}, delay);
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
timeout = setTimeout(fn, delay);
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { onMounted, onUnmounted } from 'vue';
|
|
2
|
+
import { throttleAndDebounce } from '../support/utils';
|
|
3
|
+
/**
|
|
4
|
+
* Defines grid configuration for each sponsor size in touple.
|
|
5
|
+
*
|
|
6
|
+
* [Screen widh, Column size]
|
|
7
|
+
*
|
|
8
|
+
* It sets grid size on matching screen size. For example, `[768, 5]` will set
|
|
9
|
+
* 5 columns when screen size is bigger or equal to 768px.
|
|
10
|
+
*
|
|
11
|
+
* Column will set only when item size is bigger than the column size. For
|
|
12
|
+
* example, even we want 5 columns, if we only have 1 sponsor yet, we would
|
|
13
|
+
* like to show it in 1 column.
|
|
14
|
+
*/
|
|
15
|
+
const GridSettings = {
|
|
16
|
+
small: [
|
|
17
|
+
[920, 6],
|
|
18
|
+
[768, 5],
|
|
19
|
+
[640, 4],
|
|
20
|
+
[480, 3],
|
|
21
|
+
[0, 2]
|
|
22
|
+
],
|
|
23
|
+
medium: [
|
|
24
|
+
[960, 5],
|
|
25
|
+
[832, 4],
|
|
26
|
+
[640, 3],
|
|
27
|
+
[480, 2]
|
|
28
|
+
],
|
|
29
|
+
big: [
|
|
30
|
+
[832, 3],
|
|
31
|
+
[640, 2]
|
|
32
|
+
]
|
|
33
|
+
};
|
|
34
|
+
export function useSponsorsGrid(options) {
|
|
35
|
+
const onResize = throttleAndDebounce(manage, 100);
|
|
36
|
+
onMounted(() => {
|
|
37
|
+
manage();
|
|
38
|
+
window.addEventListener('resize', onResize);
|
|
39
|
+
});
|
|
40
|
+
onUnmounted(() => {
|
|
41
|
+
window.removeEventListener('resize', onResize);
|
|
42
|
+
});
|
|
43
|
+
function manage() {
|
|
44
|
+
adjustSlots(options.el.value, options.size);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function adjustSlots(el, size) {
|
|
48
|
+
const tsize = el.children.length;
|
|
49
|
+
const asize = el.querySelectorAll('.vp-sponsor-grid-item:not(.empty)').length;
|
|
50
|
+
const grid = setGrid(el, size, asize);
|
|
51
|
+
manageSlots(el, grid, tsize, asize);
|
|
52
|
+
}
|
|
53
|
+
function setGrid(el, size, items) {
|
|
54
|
+
const settings = GridSettings[size];
|
|
55
|
+
const screen = window.innerWidth;
|
|
56
|
+
let grid = 1;
|
|
57
|
+
settings.some(([breakpoint, value]) => {
|
|
58
|
+
if (screen >= breakpoint) {
|
|
59
|
+
grid = items < value ? items : value;
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
setGridData(el, grid);
|
|
64
|
+
return grid;
|
|
65
|
+
}
|
|
66
|
+
function setGridData(el, value) {
|
|
67
|
+
el.dataset.vpGrid = String(value);
|
|
68
|
+
}
|
|
69
|
+
function manageSlots(el, grid, tsize, asize) {
|
|
70
|
+
const diff = tsize - asize;
|
|
71
|
+
const rem = asize % grid;
|
|
72
|
+
const drem = rem === 0 ? rem : grid - rem;
|
|
73
|
+
neutralizeSlots(el, drem - diff);
|
|
74
|
+
}
|
|
75
|
+
function neutralizeSlots(el, count) {
|
|
76
|
+
if (count === 0) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
count > 0 ? addSlots(el, count) : removeSlots(el, count * -1);
|
|
80
|
+
}
|
|
81
|
+
function addSlots(el, count) {
|
|
82
|
+
for (let i = 0; i < count; i++) {
|
|
83
|
+
const slot = document.createElement('div');
|
|
84
|
+
slot.classList.add('vp-sponsor-grid-item', 'empty');
|
|
85
|
+
el.append(slot);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function removeSlots(el, count) {
|
|
89
|
+
for (let i = 0; i < count; i++) {
|
|
90
|
+
el.removeChild(el.lastElementChild);
|
|
91
|
+
}
|
|
92
|
+
}
|