valaxy 0.11.0 → 0.11.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/client/App.vue +9 -2
- package/client/components/AppLink.vue +3 -0
- package/client/components/ValaxyAddons.vue +0 -2
- package/client/components/ValaxyMd.vue +5 -1
- package/client/composables/{outline.ts → outline/anchor.ts} +2 -48
- package/client/composables/outline/headers.ts +124 -0
- package/client/composables/outline/index.ts +2 -0
- package/client/composables/sidebar.ts +0 -1
- package/client/layouts/404.vue +4 -10
- package/client/main.ts +1 -2
- package/client/pages/[...all].vue +1 -1
- package/client/styles/common/code.scss +19 -0
- package/client/styles/common/custom-blocks.scss +3 -1
- package/client/styles/common/scrollbar.scss +3 -2
- package/client/styles/vars.scss +1 -3
- package/client/styles/widgets/banner.scss +8 -4
- package/dist/chunk-7E4ZKF2A.cjs +100 -0
- package/dist/chunk-ADF3MCMP.mjs +100 -0
- package/dist/{config-a8e39079.d.ts → config-9d0ecaef.d.ts} +27 -4
- package/dist/node/cli.cjs +7 -7
- package/dist/node/cli.mjs +7 -7
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.ts +47 -29
- package/dist/node/index.mjs +1 -1
- package/dist/types/index.d.ts +23 -3
- package/package.json +27 -23
- package/types/addon.ts +6 -0
- package/types/config.ts +21 -1
- package/types/data.ts +24 -0
- package/types/index.ts +1 -0
- package/dist/chunk-GFYAQP2J.cjs +0 -100
- package/dist/chunk-NUT63HGX.mjs +0 -100
package/client/App.vue
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue'
|
|
2
|
+
import { computed, provide, ref } from 'vue'
|
|
3
3
|
import { useHead } from '@vueuse/head'
|
|
4
4
|
// @ts-expect-error virtual module
|
|
5
5
|
import ValaxyUserApp from '/@valaxyjs/UserAppVue'
|
|
6
|
+
// @ts-expect-error virtual module
|
|
7
|
+
import ValaxyThemeApp from '/@valaxyjs/ThemeAppVue'
|
|
8
|
+
import ValaxyAddons from './components/ValaxyAddons.vue'
|
|
6
9
|
import { isDark } from './composables'
|
|
7
10
|
|
|
8
11
|
// https://github.com/vueuse/head
|
|
@@ -36,10 +39,14 @@ useHead({
|
|
|
36
39
|
},
|
|
37
40
|
],
|
|
38
41
|
})
|
|
42
|
+
|
|
43
|
+
const onContentUpdated = ref()
|
|
44
|
+
provide('onContentUpdated', onContentUpdated)
|
|
39
45
|
</script>
|
|
40
46
|
|
|
41
47
|
<template>
|
|
42
|
-
<
|
|
48
|
+
<ValaxyThemeApp />
|
|
43
49
|
<ValaxyAddons />
|
|
50
|
+
<ValaxyUserApp />
|
|
44
51
|
<router-view />
|
|
45
52
|
</template>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
// https://router.vuejs.org/guide/advanced/extending-router-link.html#extending-routerlink
|
|
2
3
|
import { computed } from 'vue'
|
|
3
4
|
|
|
4
5
|
const props = defineProps<{
|
|
6
|
+
showExternalIcon?: boolean
|
|
5
7
|
to: string
|
|
6
8
|
}>()
|
|
7
9
|
|
|
@@ -13,6 +15,7 @@ const isExternalLink = computed(() => {
|
|
|
13
15
|
<template>
|
|
14
16
|
<a v-if="isExternalLink" v-bind="$attrs" :href="to" target="_blank">
|
|
15
17
|
<slot />
|
|
18
|
+
<div v-if="showExternalIcon" class="icon-link inline-block" i-ri-arrow-right-up-line />
|
|
16
19
|
</a>
|
|
17
20
|
<router-link v-else v-bind="$props as any">
|
|
18
21
|
<slot />
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import {
|
|
2
|
+
import type { Ref } from 'vue'
|
|
3
|
+
import { inject, onMounted, ref } from 'vue'
|
|
3
4
|
import { useI18n } from 'vue-i18n'
|
|
4
5
|
import { useAplayer, useCodePen, useCopyCode, wrapTable } from '..'
|
|
5
6
|
import type { Post } from '../../types'
|
|
@@ -9,11 +10,14 @@ const props = defineProps<{
|
|
|
9
10
|
excerpt?: string
|
|
10
11
|
}>()
|
|
11
12
|
|
|
13
|
+
const onContentUpdated = inject('onContentUpdated') as Ref<() => void>
|
|
14
|
+
|
|
12
15
|
const { t } = useI18n()
|
|
13
16
|
|
|
14
17
|
const content = ref()
|
|
15
18
|
function updateDom() {
|
|
16
19
|
wrapTable(content.value)
|
|
20
|
+
onContentUpdated.value?.()
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
onMounted(() => {
|
|
@@ -1,52 +1,6 @@
|
|
|
1
1
|
import type { Ref } from 'vue'
|
|
2
2
|
import { onMounted, onUnmounted, onUpdated } from 'vue'
|
|
3
|
-
import { throttleAndDebounce } from '
|
|
4
|
-
import type { Header } from '../../types'
|
|
5
|
-
|
|
6
|
-
interface HeaderWithChildren extends Header {
|
|
7
|
-
children?: Header[]
|
|
8
|
-
hidden?: boolean
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface MenuItemWithLinkAndChildren {
|
|
12
|
-
text: string
|
|
13
|
-
link: string
|
|
14
|
-
children?: MenuItemWithLinkAndChildren[]
|
|
15
|
-
hidden?: boolean
|
|
16
|
-
lang?: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function resolveHeaders(headers: Header[]) {
|
|
20
|
-
return mapHeaders(groupHeaders(headers))
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function groupHeaders(headers: Header[]): HeaderWithChildren[] {
|
|
24
|
-
headers = headers.map(h => Object.assign({}, h))
|
|
25
|
-
|
|
26
|
-
let lastH2: HeaderWithChildren | undefined
|
|
27
|
-
|
|
28
|
-
for (const h of headers) {
|
|
29
|
-
if (h.level === 2)
|
|
30
|
-
lastH2 = h
|
|
31
|
-
|
|
32
|
-
else if (lastH2 && h.level <= 3)
|
|
33
|
-
(lastH2.children || (lastH2.children = [])).push(h)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return headers.filter(h => h.level === 2)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function mapHeaders(
|
|
40
|
-
headers: HeaderWithChildren[],
|
|
41
|
-
): MenuItemWithLinkAndChildren[] {
|
|
42
|
-
return headers.map(header => ({
|
|
43
|
-
text: header.title,
|
|
44
|
-
link: `#${header.slug}`,
|
|
45
|
-
children: header.children ? mapHeaders(header.children) : undefined,
|
|
46
|
-
hidden: header.hidden,
|
|
47
|
-
lang: header.lang,
|
|
48
|
-
}))
|
|
49
|
-
}
|
|
3
|
+
import { throttleAndDebounce } from '../../utils'
|
|
50
4
|
|
|
51
5
|
// magic number to avoid repeated retrieval
|
|
52
6
|
const PAGE_OFFSET = 56
|
|
@@ -89,7 +43,7 @@ export function useActiveAnchor(
|
|
|
89
43
|
const scrollY = window.scrollY
|
|
90
44
|
const innerHeight = window.innerHeight
|
|
91
45
|
const offsetHeight = container.value.offsetHeight
|
|
92
|
-
const isBottom =
|
|
46
|
+
const isBottom = scrollY + innerHeight === offsetHeight
|
|
93
47
|
|
|
94
48
|
// console.log(scrollY, innerHeight, offsetHeight)
|
|
95
49
|
// console.log(isBottom)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { Ref } from 'vue'
|
|
2
|
+
import { computed, inject, ref } from 'vue'
|
|
3
|
+
import type { DefaultThemeConfig, Header } from 'valaxy/types'
|
|
4
|
+
import { useFrontmatter, useThemeConfig } from '../..'
|
|
5
|
+
|
|
6
|
+
export type MenuItem = Omit<Header, 'slug' | 'children'> & {
|
|
7
|
+
children?: MenuItem[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function resolveHeaders(
|
|
11
|
+
headers: MenuItem[],
|
|
12
|
+
levelsRange: Exclude<DefaultThemeConfig['outline'], false> = [2, 4],
|
|
13
|
+
) {
|
|
14
|
+
const levels: [number, number]
|
|
15
|
+
= typeof levelsRange === 'number'
|
|
16
|
+
? [levelsRange, levelsRange]
|
|
17
|
+
: levelsRange === 'deep'
|
|
18
|
+
? [2, 6]
|
|
19
|
+
: levelsRange
|
|
20
|
+
|
|
21
|
+
return groupHeaders(headers, levels)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function groupHeaders(headers: MenuItem[], levelsRange: [number, number]) {
|
|
25
|
+
const result: MenuItem[] = []
|
|
26
|
+
|
|
27
|
+
headers = headers.map(h => ({ ...h }))
|
|
28
|
+
headers.forEach((h, index) => {
|
|
29
|
+
if (h.level >= levelsRange[0] && h.level <= levelsRange[1]) {
|
|
30
|
+
if (addToParent(index, headers, levelsRange))
|
|
31
|
+
result.push(h)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return result
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function addToParent(
|
|
39
|
+
currIndex: number,
|
|
40
|
+
headers: MenuItem[],
|
|
41
|
+
levelsRange: [number, number],
|
|
42
|
+
) {
|
|
43
|
+
if (currIndex === 0)
|
|
44
|
+
return true
|
|
45
|
+
|
|
46
|
+
const currentHeader = headers[currIndex]
|
|
47
|
+
for (let index = currIndex - 1; index >= 0; index--) {
|
|
48
|
+
const header = headers[index]
|
|
49
|
+
|
|
50
|
+
if (
|
|
51
|
+
header.level < currentHeader.level
|
|
52
|
+
&& header.level >= levelsRange[0]
|
|
53
|
+
&& header.level <= levelsRange[1]
|
|
54
|
+
) {
|
|
55
|
+
if (header.children == null)
|
|
56
|
+
header.children = []
|
|
57
|
+
header.children.push(currentHeader)
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* export headers & handleClick to generate outline
|
|
67
|
+
* @returns
|
|
68
|
+
*/
|
|
69
|
+
export const useOutline = () => {
|
|
70
|
+
const frontmatter = useFrontmatter()
|
|
71
|
+
const themeConfig = useThemeConfig()
|
|
72
|
+
const headers = ref<MenuItem[]>([])
|
|
73
|
+
const pageOutline = computed<DefaultThemeConfig['outline']>(
|
|
74
|
+
() => frontmatter.value.outline ?? themeConfig.value.outline,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
const onContentUpdated = inject('onContentUpdated') as Ref<() => void>
|
|
78
|
+
onContentUpdated.value = () => {
|
|
79
|
+
headers.value = getHeaders(pageOutline.value)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const handleClick = ({ target: el }: Event) => {
|
|
83
|
+
const id = `#${(el as HTMLAnchorElement).href!.split('#')[1]}`
|
|
84
|
+
const heading = document.querySelector(
|
|
85
|
+
decodeURIComponent(id),
|
|
86
|
+
) as HTMLAnchorElement
|
|
87
|
+
heading?.focus()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
/**
|
|
92
|
+
* headers for toc
|
|
93
|
+
*/
|
|
94
|
+
headers,
|
|
95
|
+
/**
|
|
96
|
+
* click hash heading
|
|
97
|
+
*/
|
|
98
|
+
handleClick,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* get headers from document directly
|
|
104
|
+
* @param pageOutline
|
|
105
|
+
* @returns
|
|
106
|
+
*/
|
|
107
|
+
export function getHeaders(pageOutline: DefaultThemeConfig['outline']) {
|
|
108
|
+
if (pageOutline === false)
|
|
109
|
+
return []
|
|
110
|
+
const updatedHeaders: MenuItem[] = []
|
|
111
|
+
document
|
|
112
|
+
.querySelectorAll<HTMLHeadingElement>('h2, h3, h4, h5, h6')
|
|
113
|
+
.forEach((el) => {
|
|
114
|
+
if (el.textContent && el.id) {
|
|
115
|
+
updatedHeaders.push({
|
|
116
|
+
level: Number(el.tagName[1]),
|
|
117
|
+
title: el.innerText.replace(/\s+#\s*$/, ''),
|
|
118
|
+
link: `#${el.id}`,
|
|
119
|
+
lang: el.lang,
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
return resolveHeaders(updatedHeaders, pageOutline)
|
|
124
|
+
}
|
package/client/layouts/404.vue
CHANGED
|
@@ -7,23 +7,17 @@ const { t } = useI18n()
|
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
9
|
<template>
|
|
10
|
-
<ValaxySidebar>
|
|
11
|
-
<slot name="sidebar">
|
|
12
|
-
<YunSidebar />
|
|
13
|
-
</slot>
|
|
14
|
-
</ValaxySidebar>
|
|
15
|
-
|
|
16
10
|
<main class="va-main" text="center">
|
|
17
|
-
<
|
|
18
|
-
<div text-
|
|
11
|
+
<div m="4" p="10" text="yellow-600">
|
|
12
|
+
<div text-6xl>
|
|
19
13
|
<div i-ri-alarm-warning-line inline-block />
|
|
20
14
|
</div>
|
|
21
15
|
<router-view />
|
|
22
16
|
<div>
|
|
23
|
-
<button btn text
|
|
17
|
+
<button class="btn rounded-full" p="x-6 y-2" text="sm" m="3 t8" :title="t('button.back')" @click="router.back()">
|
|
24
18
|
{{ t('button.back') }}
|
|
25
19
|
</button>
|
|
26
20
|
</div>
|
|
27
|
-
</
|
|
21
|
+
</div>
|
|
28
22
|
</main>
|
|
29
23
|
</template>
|
package/client/main.ts
CHANGED
|
@@ -4,11 +4,10 @@ import { setupLayouts } from 'virtual:generated-layouts'
|
|
|
4
4
|
import App from './App.vue'
|
|
5
5
|
|
|
6
6
|
import '@unocss/reset/tailwind.css'
|
|
7
|
-
|
|
8
7
|
// generate user styles
|
|
9
8
|
import '/@valaxyjs/styles'
|
|
10
|
-
|
|
11
9
|
import 'uno.css'
|
|
10
|
+
|
|
12
11
|
import setupMain from './setup/main'
|
|
13
12
|
|
|
14
13
|
const routes = setupLayouts(__DEV__ ? generatedRoutes : generatedRoutes.filter(i => !i.meta?.frontmatter.draft))
|
|
@@ -22,9 +22,15 @@
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
.markdown-body {
|
|
25
|
+
code {
|
|
26
|
+
// relative h1, etc
|
|
27
|
+
font-size: 0.85em;
|
|
28
|
+
}
|
|
29
|
+
|
|
25
30
|
div[class*="language-"] {
|
|
26
31
|
position: relative;
|
|
27
32
|
background-color: var(--va-code-block-bg);
|
|
33
|
+
overflow-x: auto;
|
|
28
34
|
|
|
29
35
|
code {
|
|
30
36
|
padding: 0 24px;
|
|
@@ -33,6 +39,19 @@
|
|
|
33
39
|
color: var(--va-code-block-color);
|
|
34
40
|
transition: color 0.5s;
|
|
35
41
|
width: fit-content;
|
|
42
|
+
|
|
43
|
+
text-align: left;
|
|
44
|
+
white-space: pre;
|
|
45
|
+
word-spacing: normal;
|
|
46
|
+
word-break: normal;
|
|
47
|
+
word-wrap: normal;
|
|
48
|
+
-moz-tab-size: 4;
|
|
49
|
+
-o-tab-size: 4;
|
|
50
|
+
tab-size: 4;
|
|
51
|
+
-webkit-hyphens: none;
|
|
52
|
+
-moz-hyphens: none;
|
|
53
|
+
-ms-hyphens: none;
|
|
54
|
+
hyphens: none;
|
|
36
55
|
}
|
|
37
56
|
|
|
38
57
|
pre {
|
|
@@ -13,16 +13,17 @@
|
|
|
13
13
|
::-webkit-scrollbar-thumb {
|
|
14
14
|
border-radius: 2px;
|
|
15
15
|
background-color: rgba(122, 122, 122, 0.3);
|
|
16
|
+
// transition not work
|
|
16
17
|
|
|
17
18
|
&:window-inactive {
|
|
18
19
|
background-color: rgba(122, 122, 122, 0.3);
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
&:hover {
|
|
22
|
-
background-color: rgba(
|
|
23
|
+
background-color: rgba(122, 122, 122, 0.7);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
&:active {
|
|
26
|
-
background-color: rgba(
|
|
27
|
+
background-color: rgba(122, 122, 122, 0.9);
|
|
27
28
|
}
|
|
28
29
|
}
|
package/client/styles/vars.scss
CHANGED
|
@@ -22,9 +22,7 @@ $font: map.merge(
|
|
|
22
22
|
"sans":
|
|
23
23
|
'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif',
|
|
24
24
|
"mono": 'Menlo, Monaco, Consolas, "Courier New", monospace',
|
|
25
|
-
"serif":
|
|
26
|
-
"'Songti SC', 'Noto Serif SC', STZhongsong, STKaiti, KaiTi, Roboto, serif",
|
|
27
|
-
"serif-weight": 900,
|
|
25
|
+
"serif": "'Noto Serif SC', STZhongsong, STKaiti, KaiTi, Roboto, serif",
|
|
28
26
|
),
|
|
29
27
|
$font
|
|
30
28
|
);
|
|
@@ -19,7 +19,8 @@ $char-animation-duration: 0.4s;
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
.vertical-line {
|
|
22
|
-
&-top,
|
|
22
|
+
&-top,
|
|
23
|
+
&-bottom {
|
|
23
24
|
display: flex;
|
|
24
25
|
background-color: var(--banner-line-color);
|
|
25
26
|
width: 1px;
|
|
@@ -47,9 +48,9 @@ $char-animation-duration: 0.4s;
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
.char {
|
|
50
|
-
font-family: get-css-var(
|
|
51
|
+
font-family: get-css-var("font", "serif");
|
|
52
|
+
font-weight: 900;
|
|
51
53
|
font-size: var(--banner-char-size, 1rem);
|
|
52
|
-
font-weight: get-css-var('font', 'serif-weight');
|
|
53
54
|
background-color: var(--banner-char-bg-color);
|
|
54
55
|
line-height: 1;
|
|
55
56
|
|
|
@@ -99,7 +100,10 @@ $char-animation-duration: 0.4s;
|
|
|
99
100
|
|
|
100
101
|
to {
|
|
101
102
|
opacity: 1;
|
|
102
|
-
border-right-width: var(
|
|
103
|
+
border-right-width: var(
|
|
104
|
+
--banner-empty-border-size,
|
|
105
|
+
var(--banner-char-size)
|
|
106
|
+
);
|
|
103
107
|
}
|
|
104
108
|
}
|
|
105
109
|
|