valaxy 0.2.4 → 0.3.0
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/{chunk-HSIBOGUA.mjs → chunk-F4NM2FOU.mjs} +43 -43
- package/dist/{chunk-XMNH5QY2.js → chunk-PQWGL22E.js} +42 -42
- package/dist/{chunk-JARRR63D.mjs → chunk-R2IXLA5A.mjs} +1 -1
- package/dist/{chunk-RUZ4KMBM.js → chunk-WNLPZSAR.js} +1 -1
- package/dist/config-408070e9.d.ts +195 -0
- package/dist/index.d.ts +404 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/node/cli.d.ts +3 -0
- package/dist/node/cli.js +8 -8
- package/dist/node/cli.mjs +8 -8
- package/dist/node/index.d.ts +46 -0
- package/dist/node/index.js +1 -1
- package/dist/node/index.mjs +1 -1
- package/package.json +22 -23
- package/src/client/components/AppLink.vue +1 -1
- package/src/client/components/PostCard.vue +2 -2
- package/src/client/components/ValaxyCopyright.vue +2 -2
- package/src/client/components/ValaxyFooter.vue +1 -2
- package/src/client/components/ValaxyMd.vue +1 -1
- package/src/client/components/ValaxyOverlay.vue +1 -1
- package/src/client/components/ValaxyPagination.vue +2 -2
- package/src/client/components/ValaxyRightSidebar.vue +44 -3
- package/src/client/components/ValaxySidebar.vue +1 -1
- package/src/client/components/ValaxyToc.vue +30 -8
- package/src/client/composables/category.ts +7 -3
- package/src/client/composables/comments/twikoo.ts +1 -4
- package/src/client/composables/comments/waline.ts +11 -2
- package/src/client/composables/sidebar.ts +29 -44
- package/src/client/locales/zh-CN.yml +1 -1
- package/src/client/modules/pwa.ts +1 -1
- package/src/client/pages/[...all].vue +0 -0
- package/src/client/stores/app.ts +5 -0
- package/src/client/styles/common/sidebar.scss +3 -1
- package/src/client/styles/global/i18n.scss +29 -1
- package/src/client/styles/global/reset.scss +1 -1
- package/src/node/cli.ts +3 -3
- package/src/node/config.ts +9 -0
- package/src/node/markdown/headings.ts +7 -1
- package/src/node/markdown/index.ts +6 -1
- package/src/node/markdown/markdown-it-katex.ts +4 -4
- package/src/node/plugins/markdown.ts +1 -0
- package/src/node/plugins/preset.ts +1 -1
- package/src/node/plugins/unocss.ts +8 -7
- package/src/node/utils/cli.ts +1 -1
- package/src/node/vite.ts +2 -0
- package/src/types/config.ts +15 -3
- package/src/types/posts.ts +5 -0
- package/src/client/public/_headers +0 -3
- package/src/client/public/favicon.svg +0 -21
- package/src/client/public/pwa-192x192.png +0 -0
- package/src/client/public/pwa-512x512.png +0 -0
- package/src/client/public/safari-pinned-tab.svg +0 -41
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as vite from 'vite';
|
|
2
|
+
import { InlineConfig } from 'vite';
|
|
3
|
+
import { V as ValaxyConfig } from '../config-408070e9.js';
|
|
4
|
+
import 'type-fest';
|
|
5
|
+
import 'unocss/vite';
|
|
6
|
+
import 'markdown-it';
|
|
7
|
+
import 'markdown-it-anchor';
|
|
8
|
+
import 'katex';
|
|
9
|
+
import 'vite-plugin-md';
|
|
10
|
+
|
|
11
|
+
interface ResolvedValaxyOptions {
|
|
12
|
+
mode: 'dev' | 'build';
|
|
13
|
+
/**
|
|
14
|
+
* Client root path
|
|
15
|
+
* @default 'valaxy/src/client'
|
|
16
|
+
*/
|
|
17
|
+
clientRoot: string;
|
|
18
|
+
/**
|
|
19
|
+
* User root path
|
|
20
|
+
* @default process.cwd()
|
|
21
|
+
*/
|
|
22
|
+
userRoot: string;
|
|
23
|
+
/**
|
|
24
|
+
* Theme root path
|
|
25
|
+
*/
|
|
26
|
+
themeRoot: string;
|
|
27
|
+
/**
|
|
28
|
+
* Theme name
|
|
29
|
+
*/
|
|
30
|
+
theme: string;
|
|
31
|
+
/**
|
|
32
|
+
* Valaxy Config
|
|
33
|
+
*/
|
|
34
|
+
config: ValaxyConfig;
|
|
35
|
+
/**
|
|
36
|
+
* config file path
|
|
37
|
+
*/
|
|
38
|
+
configFile: string;
|
|
39
|
+
}
|
|
40
|
+
interface ValaxyServerOptions {
|
|
41
|
+
onConfigReload?: (newConfig: ValaxyConfig, config: ValaxyConfig) => void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
declare function createServer(options: ResolvedValaxyOptions, viteConfig?: InlineConfig, serverOptions?: ValaxyServerOptions): Promise<vite.ViteDevServer>;
|
|
45
|
+
|
|
46
|
+
export { createServer };
|
package/dist/node/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkPQWGL22Ejs = require('../chunk-PQWGL22E.js');var _chunkWNLPZSARjs = require('../chunk-WNLPZSAR.js');_chunkWNLPZSARjs.f.call(void 0, );exports.createServer = _chunkPQWGL22Ejs.i;
|
package/dist/node/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i as r}from"../chunk-
|
|
1
|
+
import{i as r}from"../chunk-F4NM2FOU.mjs";import{f as o}from"../chunk-R2IXLA5A.mjs";o();export{r as createServer};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "valaxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "📄 Vite & Vue powered static blog generator.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -37,26 +37,26 @@
|
|
|
37
37
|
"https-localhost": "^4.7.1",
|
|
38
38
|
"markdown-it-attrs": "^4.1.3",
|
|
39
39
|
"type-fest": "^2.12.2",
|
|
40
|
-
"vue-tsc": "^0.34.
|
|
40
|
+
"vue-tsc": "^0.34.11"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@ctrl/tinycolor": "^3.4.
|
|
44
|
-
"@iconify-json/carbon": "^1.1.
|
|
43
|
+
"@ctrl/tinycolor": "^3.4.1",
|
|
44
|
+
"@iconify-json/carbon": "^1.1.4",
|
|
45
45
|
"@iconify-json/ri": "^1.1.1",
|
|
46
46
|
"@intlify/vite-plugin-vue-i18n": "^3.4.0",
|
|
47
47
|
"@vitejs/plugin-vue": "^2.3.1",
|
|
48
|
-
"@vueuse/core": "^8.
|
|
49
|
-
"@vueuse/head": "^0.7.
|
|
48
|
+
"@vueuse/core": "^8.3.1",
|
|
49
|
+
"@vueuse/head": "^0.7.6",
|
|
50
50
|
"consola": "^2.15.3",
|
|
51
51
|
"critters": "^0.0.16",
|
|
52
|
-
"dayjs": "^1.11.
|
|
52
|
+
"dayjs": "^1.11.1",
|
|
53
53
|
"escape-html": "^1.0.3",
|
|
54
54
|
"fast-deep-equal": "^3.1.3",
|
|
55
55
|
"feed": "^4.2.2",
|
|
56
56
|
"katex": "^0.15.3",
|
|
57
57
|
"markdown-it-anchor": "^8.6.2",
|
|
58
58
|
"markdown-it-container": "^3.0.0",
|
|
59
|
-
"markdown-it-emoji": "^2.0.
|
|
59
|
+
"markdown-it-emoji": "^2.0.2",
|
|
60
60
|
"markdown-it-link-attributes": "^4.0.0",
|
|
61
61
|
"markdown-it-table-of-contents": "^0.6.0",
|
|
62
62
|
"markdown-it-task-lists": "^2.1.1",
|
|
@@ -64,23 +64,23 @@
|
|
|
64
64
|
"open": "^8.4.0",
|
|
65
65
|
"pinia": "^2.0.13",
|
|
66
66
|
"prism-theme-vars": "^0.2.2",
|
|
67
|
-
"prismjs": "^1.
|
|
68
|
-
"sass": "^1.
|
|
67
|
+
"prismjs": "^1.28.0",
|
|
68
|
+
"sass": "^1.51.0",
|
|
69
69
|
"star-markdown-css": "^0.3.3",
|
|
70
|
-
"unconfig": "^0.3.
|
|
71
|
-
"unocss": "^0.
|
|
72
|
-
"unplugin-vue-components": "^0.19.
|
|
73
|
-
"vite": "^2.9.
|
|
74
|
-
"vite-plugin-inspect": "^0.
|
|
75
|
-
"vite-plugin-md": "^0.
|
|
76
|
-
"vite-plugin-pages": "^0.
|
|
77
|
-
"vite-plugin-pwa": "^0.
|
|
70
|
+
"unconfig": "^0.3.3",
|
|
71
|
+
"unocss": "^0.32.9",
|
|
72
|
+
"unplugin-vue-components": "^0.19.3",
|
|
73
|
+
"vite": "^2.9.7",
|
|
74
|
+
"vite-plugin-inspect": "^0.5.0",
|
|
75
|
+
"vite-plugin-md": "^0.13.0",
|
|
76
|
+
"vite-plugin-pages": "^0.23.0",
|
|
77
|
+
"vite-plugin-pwa": "^0.12.0",
|
|
78
78
|
"vite-plugin-vue-layouts": "^0.6.0",
|
|
79
79
|
"vite-ssg": "^0.19.2",
|
|
80
|
-
"vite-ssg-sitemap": "0.2.
|
|
81
|
-
"vue": "^3.2.
|
|
80
|
+
"vite-ssg-sitemap": "0.2.6",
|
|
81
|
+
"vue": "^3.2.33",
|
|
82
82
|
"vue-demi": "^0.12.5",
|
|
83
|
-
"vue-i18n": "^9.1.
|
|
83
|
+
"vue-i18n": "^9.1.10",
|
|
84
84
|
"vue-router": "^4.0.14",
|
|
85
85
|
"yargs": "^17.4.1"
|
|
86
86
|
},
|
|
@@ -91,6 +91,5 @@
|
|
|
91
91
|
"preview": "vite preview",
|
|
92
92
|
"preview-https": "serve dist",
|
|
93
93
|
"typecheck": "vue-tsc --noEmit"
|
|
94
|
-
}
|
|
95
|
-
"readme": "# Valaxy\n\n🌌 Next Generation Static Blog Framework, powered by Vite & Vue.\n\nRead [YunYouJun/valaxy](https://github.com/YunYouJun/valaxy) for more info.\n"
|
|
94
|
+
}
|
|
96
95
|
}
|
|
@@ -14,7 +14,7 @@ const isExternalLink = computed(() => {
|
|
|
14
14
|
<a v-if="isExternalLink" v-bind="$attrs" :href="to" target="_blank">
|
|
15
15
|
<slot />
|
|
16
16
|
</a>
|
|
17
|
-
<router-link v-else v-bind="$props">
|
|
17
|
+
<router-link v-else v-bind="$props as any">
|
|
18
18
|
<slot />
|
|
19
19
|
</router-link>
|
|
20
20
|
</template>
|
|
@@ -46,7 +46,7 @@ const { icon, styles } = usePostProperty(props.post.type)
|
|
|
46
46
|
v-if="post.categories"
|
|
47
47
|
:to="{
|
|
48
48
|
path: '/categories/',
|
|
49
|
-
query: {category: Array.isArray(post.categories) ? post.categories[post.categories.length - 1] : post.categories}
|
|
49
|
+
query: { category: Array.isArray(post.categories) ? post.categories[post.categories.length - 1] : post.categories },
|
|
50
50
|
}"
|
|
51
51
|
class="post-categories inline-flex justify-center items-center" m="l-2"
|
|
52
52
|
>
|
|
@@ -57,7 +57,7 @@ const { icon, styles } = usePostProperty(props.post.type)
|
|
|
57
57
|
|
|
58
58
|
<div class="post-tags inline-flex" m="r-2">
|
|
59
59
|
<template v-if="post.tags">
|
|
60
|
-
<router-link v-for="tag,i in post.tags" :key="i" :to="{path: '/tags/', query: {tag
|
|
60
|
+
<router-link v-for="tag, i in post.tags" :key="i" :to="{ path: '/tags/', query: { tag } }" m="x-1" class="post-tag inline-flex justify-center items-center">
|
|
61
61
|
<div m="r-1" i-ri-price-tag-3-line />
|
|
62
62
|
{{ tag }}
|
|
63
63
|
</router-link>
|
|
@@ -3,14 +3,14 @@ import { computed } from 'vue'
|
|
|
3
3
|
import { useI18n } from 'vue-i18n'
|
|
4
4
|
import { useConfig } from '../config'
|
|
5
5
|
|
|
6
|
-
const { t, locale } = useI18n()
|
|
7
|
-
|
|
8
6
|
withDefaults(defineProps<{
|
|
9
7
|
url?: string
|
|
10
8
|
}>(), {
|
|
11
9
|
url: '',
|
|
12
10
|
})
|
|
13
11
|
|
|
12
|
+
const { t, locale } = useI18n()
|
|
13
|
+
|
|
14
14
|
const config = useConfig()
|
|
15
15
|
|
|
16
16
|
const ccVersion = (config.value.license.type === 'zero') ? '1.0' : '4.0'
|
|
@@ -3,7 +3,6 @@ import { capitalize, computed } from 'vue'
|
|
|
3
3
|
import { useConfig, useThemeConfig } from 'valaxy'
|
|
4
4
|
import { useI18n } from 'vue-i18n'
|
|
5
5
|
|
|
6
|
-
import themePkg from 'valaxy-theme-yun/package.json'
|
|
7
6
|
import pkg from '~/../../package.json'
|
|
8
7
|
|
|
9
8
|
const { t } = useI18n()
|
|
@@ -45,7 +44,7 @@ const poweredHtml = computed(() => t('footer.powered', [`<a href="${pkg.reposito
|
|
|
45
44
|
</div>
|
|
46
45
|
|
|
47
46
|
<div v-if="themeConfig.footer.powered" class="powered" m="2">
|
|
48
|
-
<span v-html="poweredHtml" /> | <span>{{ t('footer.theme') }} - <a :href="
|
|
47
|
+
<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
48
|
</div>
|
|
50
49
|
|
|
51
50
|
<slot />
|
|
@@ -34,7 +34,7 @@ if (props.frontmatter.codepen)
|
|
|
34
34
|
</script>
|
|
35
35
|
|
|
36
36
|
<template>
|
|
37
|
-
<article v-if="$slots.default" class="markdown-body">
|
|
37
|
+
<article v-if="$slots.default" :class="frontmatter.markdown !== false && 'markdown-body'">
|
|
38
38
|
<slot ref="content" @vnode-updated="updateDom" />
|
|
39
39
|
|
|
40
40
|
<div text="center">
|
|
@@ -15,7 +15,7 @@ const props = defineProps<{
|
|
|
15
15
|
pageSize: number
|
|
16
16
|
}>()
|
|
17
17
|
|
|
18
|
-
const emit = defineEmits(['
|
|
18
|
+
const emit = defineEmits(['pageChange'])
|
|
19
19
|
|
|
20
20
|
const totalPages = computed(() => Math.ceil(props.total / props.pageSize))
|
|
21
21
|
|
|
@@ -38,7 +38,7 @@ const showPage = (i: number) => {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const jumpTo = (page: number) => {
|
|
41
|
-
emit('
|
|
41
|
+
emit('pageChange', page)
|
|
42
42
|
if (page === 1)
|
|
43
43
|
return '/'
|
|
44
44
|
else return `/page/${page}`
|
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { useI18n } from 'vue-i18n'
|
|
3
3
|
import type { Post } from '../../types'
|
|
4
|
+
import { useAppStore } from '~/stores/app'
|
|
5
|
+
defineProps<{ frontmatter: Post }>()
|
|
4
6
|
const { t } = useI18n()
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
const app = useAppStore()
|
|
7
9
|
</script>
|
|
8
10
|
|
|
9
11
|
<template>
|
|
10
|
-
<
|
|
12
|
+
<button
|
|
13
|
+
class="xl:hidden toc-btn shadow fixed yun-icon-btn z-350"
|
|
14
|
+
opacity="75" right="2" bottom="19"
|
|
15
|
+
@click="app.toggleRightSidebar()"
|
|
16
|
+
>
|
|
17
|
+
<div i-ri-file-list-line />
|
|
18
|
+
</button>
|
|
19
|
+
|
|
20
|
+
<ValaxyOverlay :show="app.isRightSidebarOpen" @click="app.toggleRightSidebar()" />
|
|
21
|
+
|
|
22
|
+
<aside class="right-sidebar fixed va-card" :class="app.isRightSidebarOpen && 'open'" m="l-4" text="center">
|
|
11
23
|
<h2 v-if="frontmatter.toc !== false" m="t-6 b-2" font="serif black">
|
|
12
24
|
{{ t('sidebar.toc') }}
|
|
13
25
|
</h2>
|
|
14
26
|
|
|
15
|
-
<div class="right-sidebar-container
|
|
27
|
+
<div class="right-sidebar-container">
|
|
16
28
|
<ValaxyToc v-if="frontmatter.toc !== false" />
|
|
17
29
|
|
|
18
30
|
<div v-if="$slots.custom" class="custom-container">
|
|
@@ -23,10 +35,39 @@ defineProps<{ frontmatter: Post }>()
|
|
|
23
35
|
</template>
|
|
24
36
|
|
|
25
37
|
<style lang="scss">
|
|
38
|
+
@use '~/styles/mixins' as *;
|
|
39
|
+
|
|
40
|
+
@include xl {
|
|
41
|
+
.right-sidebar {
|
|
42
|
+
transform: translateX(0) !important;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
26
46
|
.right-sidebar {
|
|
27
47
|
width: var(--va-sidebar-width-mobile);
|
|
48
|
+
|
|
49
|
+
position: fixed;
|
|
50
|
+
top: 0;
|
|
51
|
+
bottom: 0;
|
|
52
|
+
right: 0;
|
|
53
|
+
|
|
54
|
+
transform: translateX(100%);
|
|
55
|
+
|
|
56
|
+
transition: box-shadow var(--va-transition-duration),
|
|
57
|
+
background-color var(--va-transition-duration), opacity 0.25s,
|
|
58
|
+
transform var(--va-transition-duration) cubic-bezier(0.19, 1, 0.22, 1);
|
|
59
|
+
|
|
60
|
+
&.open {
|
|
61
|
+
z-index: 10;
|
|
62
|
+
transform: translateX(0);
|
|
63
|
+
}
|
|
28
64
|
}
|
|
29
65
|
.right-sidebar-container {
|
|
30
66
|
top: 1rem;
|
|
31
67
|
}
|
|
68
|
+
|
|
69
|
+
.toc-btn {
|
|
70
|
+
color: var(--va-c-primary);
|
|
71
|
+
background-color: white;
|
|
72
|
+
}
|
|
32
73
|
</style>
|
|
@@ -11,7 +11,7 @@ const isHome = useLayout('home')
|
|
|
11
11
|
|
|
12
12
|
<ValaxyHamburger :active="app.isSidebarOpen" class="menu-btn sidebar-toggle yun-icon-btn" :class="isHome ? '' : 'md:hidden'" @click="app.toggleSidebar()" />
|
|
13
13
|
|
|
14
|
-
<aside class="va-card" :class="[
|
|
14
|
+
<aside class="va-card transition sidebar" :class="[app.isSidebarOpen && 'open', !isHome && 'md:translate-x-0']">
|
|
15
15
|
<slot />
|
|
16
16
|
</aside>
|
|
17
17
|
</template>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { computed } from 'vue'
|
|
2
|
+
import { computed, ref } from 'vue'
|
|
3
|
+
import { useI18n } from 'vue-i18n'
|
|
3
4
|
import { useRoute } from 'vue-router'
|
|
4
5
|
|
|
5
6
|
import { useActiveSidebarLinks } from '~/composables'
|
|
@@ -7,27 +8,48 @@ import { useActiveSidebarLinks } from '~/composables'
|
|
|
7
8
|
const route = useRoute()
|
|
8
9
|
const headers = computed(() => route.meta.headers)
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
const container = ref()
|
|
12
|
+
const marker = ref()
|
|
13
|
+
useActiveSidebarLinks(container, marker)
|
|
11
14
|
|
|
12
15
|
function getStylesByLevel(level: number) {
|
|
13
16
|
return {
|
|
14
|
-
fontSize: `${(6 - level) * 0.
|
|
17
|
+
// fontSize: `${(6 - level) * 0.1 + 0.7}rem`,
|
|
15
18
|
paddingLeft: `${level * 1 - 1}rem`,
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
|
|
22
|
+
const { locale } = useI18n()
|
|
23
|
+
|
|
19
24
|
// todo mobile toc widget
|
|
20
25
|
</script>
|
|
21
26
|
|
|
22
27
|
<template>
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
<div v-if="headers" ref="container">
|
|
29
|
+
<div ref="marker" class="outline-marker" />
|
|
30
|
+
<ul class="va-toc" p="l-4">
|
|
31
|
+
<li v-for="header, i in headers" :key="i" :lang="header.lang || locale" class="va-toc-item" :style="getStylesByLevel(header.level)">
|
|
32
|
+
<a class="toc-link-item" :href="`#${header.slug}`">{{ header.title }}</a>
|
|
33
|
+
</li>
|
|
34
|
+
</ul>
|
|
35
|
+
</div>
|
|
28
36
|
</template>
|
|
29
37
|
|
|
30
38
|
<style lang="scss">
|
|
39
|
+
.outline-marker {
|
|
40
|
+
opacity: 0;
|
|
41
|
+
position: absolute;
|
|
42
|
+
background-color: var(--va-c-primary);
|
|
43
|
+
border-radius: 4px;
|
|
44
|
+
width: 4px;
|
|
45
|
+
height: 20px;
|
|
46
|
+
top: 32px;
|
|
47
|
+
left: 20px;
|
|
48
|
+
z-index: 0;
|
|
49
|
+
transition: top 0.25s cubic-bezier(0, 1, 0.5, 1), opacity 0.25s,
|
|
50
|
+
background-color 0.5s;
|
|
51
|
+
}
|
|
52
|
+
|
|
31
53
|
.va-toc {
|
|
32
54
|
top: 10px;
|
|
33
55
|
width: var(--yun-sidebar-width-mobile);
|
|
@@ -2,13 +2,15 @@ import { unref } from 'vue'
|
|
|
2
2
|
import type { Post } from '../../types'
|
|
3
3
|
import { usePostList } from './post'
|
|
4
4
|
|
|
5
|
-
export interface
|
|
5
|
+
export interface BaseCategory {
|
|
6
6
|
total: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ParentCategory extends BaseCategory {
|
|
7
10
|
children: Categories
|
|
8
11
|
}
|
|
9
12
|
|
|
10
|
-
export interface PostCategory {
|
|
11
|
-
total: number
|
|
13
|
+
export interface PostCategory extends BaseCategory {
|
|
12
14
|
posts: Post[]
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -17,6 +19,8 @@ export type Category = ParentCategory | PostCategory
|
|
|
17
19
|
// export type Categories = Map<string, Post[] | Category>
|
|
18
20
|
export type Categories = Map<string, Category>
|
|
19
21
|
|
|
22
|
+
export const isParentCategory = (category: any): category is ParentCategory => category.children
|
|
23
|
+
|
|
20
24
|
/**
|
|
21
25
|
* get categories from posts
|
|
22
26
|
* @returns
|
|
@@ -4,11 +4,8 @@ import { useRoute } from 'vue-router'
|
|
|
4
4
|
|
|
5
5
|
export function useTwikoo(options: {} = {}) {
|
|
6
6
|
const route = useRoute()
|
|
7
|
-
|
|
8
7
|
const { locale } = useI18n()
|
|
9
8
|
|
|
10
|
-
let twikoo: any
|
|
11
|
-
|
|
12
9
|
/**
|
|
13
10
|
* init twikoo
|
|
14
11
|
* @param options twikoo options
|
|
@@ -30,6 +27,6 @@ export function useTwikoo(options: {} = {}) {
|
|
|
30
27
|
// 直接使用 CDN
|
|
31
28
|
useScriptTag('//cdn.jsdelivr.net/npm/twikoo@1.5.1/dist/twikoo.all.min.js', () => {
|
|
32
29
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33
|
-
|
|
30
|
+
initTwikoo(options)
|
|
34
31
|
})
|
|
35
32
|
}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { isClient, useScriptTag } from '@vueuse/core'
|
|
2
|
+
import { useHead } from '@vueuse/head'
|
|
2
3
|
import { onUnmounted, watch } from 'vue'
|
|
3
4
|
import { useI18n } from 'vue-i18n'
|
|
4
5
|
import { useRoute } from 'vue-router'
|
|
5
6
|
|
|
6
7
|
export function useWaline(options: {} = {}) {
|
|
8
|
+
useHead({
|
|
9
|
+
link: [
|
|
10
|
+
{ rel: 'stylesheet', href: 'https://cdn.jsdelivr.net/npm/@waline/client/dist/waline.css' },
|
|
11
|
+
],
|
|
12
|
+
})
|
|
13
|
+
|
|
7
14
|
const route = useRoute()
|
|
8
15
|
|
|
9
16
|
const { locale } = useI18n()
|
|
@@ -31,11 +38,11 @@ export function useWaline(options: {} = {}) {
|
|
|
31
38
|
path: route.path,
|
|
32
39
|
}
|
|
33
40
|
const walineOptions = Object.assign(defaultOptions, options)
|
|
34
|
-
return window.Waline(walineOptions)
|
|
41
|
+
return window.Waline.init(walineOptions)
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
// 直接使用 CDN
|
|
38
|
-
useScriptTag('//cdn.jsdelivr.net/npm/@waline/client', () => {
|
|
45
|
+
useScriptTag('//cdn.jsdelivr.net/npm/@waline/client/dist/waline.js', () => {
|
|
39
46
|
waline = initWaline(options)
|
|
40
47
|
})
|
|
41
48
|
|
|
@@ -60,4 +67,6 @@ export function useWaline(options: {} = {}) {
|
|
|
60
67
|
return
|
|
61
68
|
waline.destroy()
|
|
62
69
|
})
|
|
70
|
+
|
|
71
|
+
return waline
|
|
63
72
|
}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Ref } from 'vue'
|
|
2
|
+
import { onMounted, onUnmounted } from 'vue'
|
|
2
3
|
|
|
3
4
|
// todo: refactor
|
|
4
5
|
|
|
5
|
-
export function useActiveSidebarLinks() {
|
|
6
|
-
let rootActiveLink: HTMLAnchorElement | null = null
|
|
7
|
-
let activeLink: HTMLAnchorElement | null = null
|
|
8
|
-
|
|
6
|
+
export function useActiveSidebarLinks(container: Ref<HTMLElement>, marker: Ref<HTMLElement>) {
|
|
9
7
|
const onScroll = throttleAndDebounce(setActiveLink, 200)
|
|
10
8
|
|
|
11
9
|
function setActiveLink(): void {
|
|
12
|
-
const sidebarLinks =
|
|
13
|
-
|
|
10
|
+
const sidebarLinks = [].slice.call(
|
|
11
|
+
document.querySelectorAll('.va-toc a.toc-link-item'),
|
|
12
|
+
) as HTMLAnchorElement[]
|
|
13
|
+
|
|
14
|
+
const anchors = [].slice
|
|
15
|
+
.call(document.querySelectorAll('main .header-anchor'))
|
|
16
|
+
.filter((anchor: HTMLAnchorElement) =>
|
|
17
|
+
sidebarLinks.some(sidebarLink => sidebarLink.hash === anchor.hash),
|
|
18
|
+
) as HTMLAnchorElement[]
|
|
14
19
|
|
|
15
20
|
for (let i = 0; i < anchors.length; i++) {
|
|
16
21
|
const anchor = anchors[i]
|
|
@@ -26,26 +31,25 @@ export function useActiveSidebarLinks() {
|
|
|
26
31
|
}
|
|
27
32
|
}
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
deactiveLink(activeLink)
|
|
31
|
-
deactiveLink(rootActiveLink)
|
|
32
|
-
|
|
33
|
-
activeLink = document.querySelector(`.va-toc a[href="${hash}"]`)
|
|
34
|
-
|
|
35
|
-
if (!activeLink)
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
activeLink.classList.add('active')
|
|
39
|
-
|
|
40
|
-
// also add active class to parent h2 anchors
|
|
41
|
-
const rootLi = activeLink.closest('.right-sidebar-container > ul > li')
|
|
34
|
+
let prevActiveLink: HTMLAnchorElement | null = null
|
|
42
35
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
function activateLink(hash: string | null): void {
|
|
37
|
+
deactiveLink(prevActiveLink)
|
|
38
|
+
|
|
39
|
+
const activeLink = (prevActiveLink
|
|
40
|
+
= hash == null
|
|
41
|
+
? null
|
|
42
|
+
: container.value.querySelector(`.va-toc a[href="${hash}"]`) as HTMLAnchorElement)
|
|
43
|
+
|
|
44
|
+
// marker animation
|
|
45
|
+
if (activeLink) {
|
|
46
|
+
activeLink.classList.add('active')
|
|
47
|
+
marker.value.style.opacity = '1'
|
|
48
|
+
marker.value.style.top = `${activeLink.offsetTop + 2}px`
|
|
46
49
|
}
|
|
47
50
|
else {
|
|
48
|
-
|
|
51
|
+
marker.value.style.opacity = '0'
|
|
52
|
+
marker.value.style.top = '54px'
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
|
|
@@ -54,34 +58,15 @@ export function useActiveSidebarLinks() {
|
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
onMounted(() => {
|
|
57
|
-
setActiveLink
|
|
61
|
+
requestAnimationFrame(setActiveLink)
|
|
58
62
|
window.addEventListener('scroll', onScroll)
|
|
59
63
|
})
|
|
60
64
|
|
|
61
|
-
onUpdated(() => {
|
|
62
|
-
// sidebar update means a route change
|
|
63
|
-
activateLink(decodeURIComponent(location.hash))
|
|
64
|
-
})
|
|
65
|
-
|
|
66
65
|
onUnmounted(() => {
|
|
67
66
|
window.removeEventListener('scroll', onScroll)
|
|
68
67
|
})
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
function getSidebarLinks(): HTMLAnchorElement[] {
|
|
72
|
-
return [].slice.call(
|
|
73
|
-
document.querySelectorAll('.va-toc a.toc-link-item'),
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function getAnchors(sidebarLinks: HTMLAnchorElement[]): HTMLAnchorElement[] {
|
|
78
|
-
return [].slice
|
|
79
|
-
.call(document.querySelectorAll('.header-anchor'))
|
|
80
|
-
.filter((anchor: HTMLAnchorElement) =>
|
|
81
|
-
sidebarLinks.some(sidebarLink => sidebarLink.hash === anchor.hash),
|
|
82
|
-
) as HTMLAnchorElement[]
|
|
83
|
-
}
|
|
84
|
-
|
|
85
70
|
function getAnchorTop(anchor: HTMLAnchorElement): number {
|
|
86
71
|
return anchor.parentElement!.offsetTop - 50
|
|
87
72
|
}
|
|
@@ -5,7 +5,7 @@ export const install: UserModule = ({ isClient, router }) => {
|
|
|
5
5
|
if (!isClient)
|
|
6
6
|
return
|
|
7
7
|
|
|
8
|
-
router.isReady().then(async() => {
|
|
8
|
+
router.isReady().then(async () => {
|
|
9
9
|
const { registerSW } = await import('virtual:pwa-register')
|
|
10
10
|
registerSW({ immediate: true })
|
|
11
11
|
})
|
|
File without changes
|
package/src/client/stores/app.ts
CHANGED
|
@@ -3,10 +3,15 @@ import { useToggle } from '@vueuse/core'
|
|
|
3
3
|
|
|
4
4
|
export const useAppStore = defineStore('app', () => {
|
|
5
5
|
const [isSidebarOpen, toggleSidebar] = useToggle(false)
|
|
6
|
+
// right sidebar with toc
|
|
7
|
+
const [isRightSidebarOpen, toggleRightSidebar] = useToggle(false)
|
|
6
8
|
|
|
7
9
|
return {
|
|
8
10
|
isSidebarOpen,
|
|
9
11
|
toggleSidebar,
|
|
12
|
+
|
|
13
|
+
isRightSidebarOpen,
|
|
14
|
+
toggleRightSidebar,
|
|
10
15
|
}
|
|
11
16
|
})
|
|
12
17
|
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
z-index: var(--yun-z-sidebar);
|
|
23
23
|
|
|
24
24
|
transform: translateX(-100%);
|
|
25
|
-
transition:
|
|
25
|
+
transition: box-shadow var(--va-transition-duration),
|
|
26
|
+
background-color var(--va-transition-duration), opacity 0.25s,
|
|
27
|
+
transform var(--va-transition-duration) cubic-bezier(0.19, 1, 0.22, 1) !important;
|
|
26
28
|
|
|
27
29
|
&.open {
|
|
28
30
|
transform: translateX(0);
|