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 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
- <ValaxyUserApp />
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 />
@@ -6,5 +6,3 @@ import addonComponents from '/@valaxyjs/addons'
6
6
  <template>
7
7
  <component :is="component" v-bind="props" v-for="({ component, props }, index) in addonComponents" :key="index" />
8
8
  </template>
9
-
10
- <style lang="scss" scoped></style>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts" setup>
2
- import { onMounted, ref } from 'vue'
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 '../utils'
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 = (scrollY + innerHeight) === offsetHeight
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
+ }
@@ -0,0 +1,2 @@
1
+ export * from './headers'
2
+ export * from './anchor'
@@ -125,7 +125,6 @@ export function useSidebar() {
125
125
  return (
126
126
  fm.value.sidebar !== false
127
127
  && layout.value !== 'home'
128
- && layout.value !== 'post'
129
128
  )
130
129
  })
131
130
 
@@ -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
- <YunCard m="4" p="10" text="yellow-600">
18
- <div text-4xl>
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-sm m="3 t8" @click="router.back()">
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
- </YunCard>
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))
@@ -4,7 +4,7 @@ const { t } = useI18n()
4
4
  </script>
5
5
 
6
6
  <template>
7
- <div>
7
+ <div m="2" text="xl">
8
8
  {{ t('not-found') }}
9
9
  </div>
10
10
  </template>
@@ -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 {
@@ -85,7 +85,9 @@ html.dark {
85
85
  align-items: center;
86
86
 
87
87
  > .icon {
88
- width: 16px;
88
+ display: inline-flex;
89
+ width: 1rem;
90
+ height: 1rem;
89
91
  margin-right: 4px;
90
92
  }
91
93
  }
@@ -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(get-css-var("c", "primary", "rgb"), 0.7);
23
+ background-color: rgba(122, 122, 122, 0.7);
23
24
  }
24
25
 
25
26
  &:active {
26
- background-color: rgba(get-css-var("c", "primary", "rgb"), 0.9);
27
+ background-color: rgba(122, 122, 122, 0.9);
27
28
  }
28
29
  }
@@ -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, &-bottom {
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('font', 'serif');
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(--banner-empty-border-size, var(--banner-char-size));
103
+ border-right-width: var(
104
+ --banner-empty-border-size,
105
+ var(--banner-char-size)
106
+ );
103
107
  }
104
108
  }
105
109