valaxy 0.18.9 → 0.19.1

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.
Files changed (44) hide show
  1. package/client/App.vue +1 -10
  2. package/client/components/ValaxyMd.vue +1 -1
  3. package/client/components/builtin/ValaxyMermaid.vue +4 -3
  4. package/client/composables/aside.ts +12 -5
  5. package/client/composables/dark.ts +77 -38
  6. package/client/composables/layout.ts +10 -2
  7. package/client/composables/sidebar.ts +41 -2
  8. package/client/locales/zh-CN.yml +1 -1
  9. package/client/main.ts +12 -10
  10. package/client/setup/main.ts +0 -2
  11. package/client/shims.d.ts +3 -0
  12. package/client/stores/app.ts +20 -4
  13. package/client/styles/css/css-vars.css +19 -0
  14. package/client/styles/{global/index.scss → css/main.css} +1 -1
  15. package/client/styles/css-vars.scss +1 -1
  16. package/client/styles/index.scss +0 -1
  17. package/client/styles/palette.scss +0 -18
  18. package/client/utils/router.ts +48 -0
  19. package/dist/chunk-O2T7UBQW.cjs +156 -0
  20. package/dist/chunk-W2X2FWTK.mjs +157 -0
  21. package/dist/{config-Kdq8Mya1.d.cts → config-Bz-Xbvue.d.cts} +102 -26
  22. package/dist/{config-Kdq8Mya1.d.ts → config-Bz-Xbvue.d.ts} +102 -26
  23. package/dist/node/cli/index.cjs +1 -1
  24. package/dist/node/cli/index.mjs +1 -1
  25. package/dist/node/index.cjs +1 -1
  26. package/dist/node/index.d.cts +2 -1
  27. package/dist/node/index.d.ts +2 -1
  28. package/dist/node/index.mjs +1 -1
  29. package/dist/types/index.cjs +1 -1
  30. package/dist/types/index.d.cts +7 -3
  31. package/dist/types/index.d.ts +7 -3
  32. package/dist/types/index.mjs +1 -1
  33. package/package.json +20 -18
  34. package/types/config.ts +5 -1
  35. package/types/default-theme.ts +38 -0
  36. package/types/frontmatter/index.ts +2 -0
  37. package/types/frontmatter/page.ts +191 -0
  38. package/types/frontmatter/post.ts +103 -0
  39. package/types/index.ts +1 -0
  40. package/types/posts.ts +1 -253
  41. package/dist/chunk-4B74DZJ5.cjs +0 -149
  42. package/dist/chunk-F2X3NOEJ.mjs +0 -150
  43. /package/dist/{chunk-42NDXDT3.mjs → chunk-7VTZAWDO.mjs} +0 -0
  44. /package/dist/{chunk-YO6XYYV3.cjs → chunk-I6UPHJXQ.cjs} +0 -0
package/client/App.vue CHANGED
@@ -16,14 +16,13 @@ import { definePerson, defineWebPage, defineWebSite, useSchemaOrg } from '@unhea
16
16
  // they will be rendered correctly in the html results with vite-ssg
17
17
  import { useSiteConfig } from './config'
18
18
  import ValaxyAddons from './components/ValaxyAddons.vue'
19
- import { isDark, useFrontmatter } from './composables'
19
+ import { useFrontmatter } from './composables'
20
20
 
21
21
  // <link rel="apple-touch-icon" href="/pwa-192x192.png">
22
22
  // <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#00aba9">
23
23
 
24
24
  const siteConfig = useSiteConfig()
25
25
  // todo, allow user config
26
- const themeColor = computed(() => isDark.value ? '#000' : '#ffffff')
27
26
  const fm = useFrontmatter()
28
27
 
29
28
  const { locale } = useI18n()
@@ -41,14 +40,6 @@ useHead({
41
40
  ],
42
41
  meta: [
43
42
  { name: 'description', content: computed(() => siteConfig.value.description) },
44
- {
45
- name: 'theme-color',
46
- content: themeColor,
47
- },
48
- {
49
- name: 'msapplication-TileColor',
50
- content: themeColor,
51
- },
52
43
  {
53
44
  name: 'generator',
54
45
  content: `Valaxy ${pkg.version}`,
@@ -44,7 +44,7 @@ useVanillaLazyLoad()
44
44
  </script>
45
45
 
46
46
  <template>
47
- <article v-if="$slots.default" :class="frontmatter.markdown !== false && 'markdown-body'">
47
+ <article v-if="$slots.default" :class="frontmatter.markdownClass || 'markdown-body'">
48
48
  <slot ref="contentRef" @vue:updated="runContentUpdated" />
49
49
 
50
50
  <div v-if="frontmatter.url" text="center">
@@ -16,11 +16,10 @@ pie
16
16
  import { getCurrentInstance, ref, watch, watchEffect } from 'vue'
17
17
 
18
18
  import { isClient } from '@vueuse/core'
19
+ import { useAppStore } from 'valaxy'
19
20
  import { renderMermaid } from '../../modules/mermaid'
20
21
  import ShadowRoot from '../internals/ShadowRoot.vue'
21
22
 
22
- import { isDark } from '../../composables'
23
-
24
23
  const props = defineProps<{
25
24
  code: string
26
25
  scale?: number
@@ -31,6 +30,8 @@ const vm = getCurrentInstance()
31
30
  const el = ref<ShadowRoot>()
32
31
  const html = ref('')
33
32
 
33
+ const appStore = useAppStore()
34
+
34
35
  if (isClient) {
35
36
  // dynamic import to reduce initial bundle size
36
37
  import('mermaid').then(m => m.default)
@@ -47,7 +48,7 @@ if (isClient) {
47
48
  mermaid,
48
49
  props.code || '',
49
50
  {
50
- theme: props.theme || (isDark.value ? 'dark' : undefined),
51
+ theme: props.theme || (appStore.isDark ? 'dark' : undefined),
51
52
  ...vm!.attrs,
52
53
  },
53
54
  )
@@ -1,11 +1,18 @@
1
- import { ref } from 'vue'
1
+ import { useMediaQuery } from '@vueuse/core'
2
+ import { useSidebar } from 'valaxy'
3
+ import { computed } from 'vue'
2
4
 
3
5
  export function useAside() {
4
- // const { hasSidebar } = useSidebar()
5
- // const is960 = useMediaQuery('(min-width: 960px)')
6
- // const is1280 = useMediaQuery('(min-width: 1280px)')
6
+ const { hasSidebar } = useSidebar()
7
+ const is960 = useMediaQuery('(min-width: 960px)')
8
+ const is1280 = useMediaQuery('(min-width: 1280px)')
7
9
 
8
- const isAsideEnabled = ref(true)
10
+ const isAsideEnabled = computed(() => {
11
+ if (!is1280.value && !is960.value)
12
+ return false
13
+
14
+ return hasSidebar.value ? is1280.value : is960.value
15
+ })
9
16
 
10
17
  return {
11
18
  isAsideEnabled,
@@ -1,44 +1,83 @@
1
- import { isClient, useDark, useToggle } from '@vueuse/core'
1
+ import type { UseDarkOptions } from '@vueuse/core'
2
+ import { useDark, useToggle } from '@vueuse/core'
3
+ import { computed } from 'vue'
2
4
 
3
- if (isClient)
4
- import('valaxy/client/styles/common/view-transition.css')
5
+ export function useValaxyDark(options: {
6
+ /**
7
+ * Options for `useDark`
8
+ * disableTransition default is `true`
9
+ * @see https://vueuse.org/core/useDark
10
+ * @url https://paco.me/writing/disable-theme-transitions
11
+ */
12
+ useDarkOptions?: UseDarkOptions
13
+ /**
14
+ * Enable circle transition when toggling dark mode
15
+ * Then use `toggleDarkWithTransition` instead of `toggleDark`
16
+ */
17
+ circleTransition?: boolean
5
18
 
6
- export const isDark = useDark()
7
- export const toggleDark = useToggle(isDark)
8
-
9
- export function toggleDarkWithTransition(event: MouseEvent, options: { duration?: number, easing?: EffectTiming['easing'] } = {}) {
10
- // @ts-expect-error startViewTransition is not defined
11
- if (!document.startViewTransition) {
12
- toggleDark()
13
- return
19
+ themeColor?: {
20
+ light?: string
21
+ dark?: string
14
22
  }
23
+ } = {}) {
24
+ const isDark = useDark(options.useDarkOptions)
25
+ const toggleDark = useToggle(isDark)
26
+
27
+ const themeColor = computed(() => isDark.value
28
+ ? (options.themeColor?.dark || '#000')
29
+ : (options.themeColor?.light || '#fff'))
30
+
31
+ if (options.circleTransition)
32
+ import('valaxy/client/styles/common/view-transition.css')
15
33
 
16
- const x = event.clientX
17
- const y = event.clientY
18
- const endRadius = Math.hypot(
19
- Math.max(x, innerWidth - x),
20
- Math.max(y, innerHeight - y),
21
- )
22
-
23
- // @ts-expect-error startViewTransition is not defined
24
- const transition = document.startViewTransition(() => {
25
- toggleDark()
26
- })
27
-
28
- transition.ready.then(() => {
29
- const clipPath = [
30
- `circle(0px at ${x}px ${y}px)`,
31
- `circle(${endRadius}px at ${x}px ${y}px)`,
32
- ]
33
- document.documentElement.animate(
34
- {
35
- clipPath: isDark.value ? clipPath.reverse() : clipPath,
36
- },
37
- {
38
- duration: options.duration || 300,
39
- easing: options.easing || 'ease-in',
40
- pseudoElement: isDark.value ? '::view-transition-old(root)' : '::view-transition-new(root)',
41
- },
34
+ function toggleDarkWithTransition(event: MouseEvent, options: { duration?: number, easing?: EffectTiming['easing'] } = {}) {
35
+ // @ts-expect-error startViewTransition is not defined
36
+ if (!document.startViewTransition) {
37
+ toggleDark()
38
+ return
39
+ }
40
+
41
+ const x = event.clientX
42
+ const y = event.clientY
43
+ const endRadius = Math.hypot(
44
+ Math.max(x, innerWidth - x),
45
+ Math.max(y, innerHeight - y),
42
46
  )
43
- })
47
+
48
+ // @ts-expect-error startViewTransition is not defined
49
+ const transition = document.startViewTransition(() => {
50
+ toggleDark()
51
+ })
52
+
53
+ transition.ready.then(() => {
54
+ const clipPath = [
55
+ `circle(0px at ${x}px ${y}px)`,
56
+ `circle(${endRadius}px at ${x}px ${y}px)`,
57
+ ]
58
+ document.documentElement.animate(
59
+ {
60
+ clipPath: isDark.value ? clipPath.reverse() : clipPath,
61
+ },
62
+ {
63
+ duration: options.duration || 300,
64
+ easing: options.easing || 'ease-in',
65
+ pseudoElement: isDark.value ? '::view-transition-old(root)' : '::view-transition-new(root)',
66
+ },
67
+ )
68
+ })
69
+ }
70
+
71
+ return {
72
+ /**
73
+ * Dark mode state, sync with app store
74
+ *
75
+ * You can also use `const appStore = useAppStore(); appStore.isDark` to get the value
76
+ */
77
+ isDark,
78
+ themeColor,
79
+
80
+ toggleDark,
81
+ toggleDarkWithTransition,
82
+ }
44
83
  }
@@ -1,10 +1,18 @@
1
+ import { useMediaQuery } from '@vueuse/core'
1
2
  import { computed } from 'vue'
2
3
  import { useRoute } from 'vue-router'
3
4
 
4
5
  export function useLayout(layout?: string) {
5
6
  const route = useRoute()
6
7
  if (layout)
7
- return computed(() => route.meta.layout === layout)
8
+ return computed(() => route.meta?.layout === layout)
8
9
  else
9
- return computed(() => route.meta.layout)
10
+ return computed(() => route.meta?.layout)
11
+ }
12
+
13
+ /**
14
+ * is mobile media query
15
+ */
16
+ export function useMobile() {
17
+ return useMediaQuery('(max-width: 768px)')
10
18
  }
@@ -1,6 +1,6 @@
1
- import { computed, ref } from 'vue'
1
+ import { computed, ref, watchEffect } from 'vue'
2
2
  import { useFrontmatter } from './common'
3
- import { useLayout } from './layout'
3
+ import { useLayout, useMobile } from './layout'
4
4
 
5
5
  /**
6
6
  * helper for sidebar
@@ -9,6 +9,7 @@ export function useSidebar() {
9
9
  const isOpen = ref(false)
10
10
  const fm = useFrontmatter()
11
11
  const layout = useLayout()
12
+
12
13
  const hasSidebar = computed(() => {
13
14
  return (
14
15
  fm.value.sidebar !== false
@@ -36,3 +37,41 @@ export function useSidebar() {
36
37
  toggle,
37
38
  }
38
39
  }
40
+
41
+ /**
42
+ * dynamic left sidebar logic
43
+ * - sidebar is hidden by default when home or mobile
44
+ * - sidebar is shown by default when not home and not mobile
45
+ * - sidebar can be toggled by user
46
+ */
47
+ export function useDynamicLeftSidebar() {
48
+ const layout = useLayout()
49
+ const isMobile = useMobile()
50
+ const isOpen = ref(isMobile.value ? false : layout.value !== 'home')
51
+
52
+ watchEffect(() => {
53
+ if (isMobile.value)
54
+ close()
55
+ else if (layout.value !== 'home')
56
+ open()
57
+ })
58
+
59
+ function open() {
60
+ isOpen.value = true
61
+ }
62
+
63
+ function close() {
64
+ isOpen.value = false
65
+ }
66
+
67
+ function toggle() {
68
+ isOpen.value ? close() : open()
69
+ }
70
+
71
+ return {
72
+ isOpen,
73
+ open,
74
+ close,
75
+ toggle,
76
+ }
77
+ }
@@ -49,7 +49,7 @@ post:
49
49
  view_link: 查看链接
50
50
  read_more: 阅读更多
51
51
  cover: 封面
52
- time_warning: '本文最后更新于{ago},文中所描述的信息可能已发生改变。'
52
+ time_warning: '本文最后更新于 {ago},文中所描述的信息可能已发生改变。'
53
53
  copyright:
54
54
  author: 本文作者
55
55
  link: 本文链接
package/client/main.ts CHANGED
@@ -1,3 +1,15 @@
1
+ // reset styles, load css before app
2
+ // import '@unocss/reset/tailwind.css'
3
+ // https://unocss.dev/guide/style-reset#tailwind-compat
4
+ // minus the background color override for buttons to avoid conflicts with UI frameworks
5
+ import '@unocss/reset/tailwind-compat.css'
6
+ // css
7
+ import './styles/css/css-vars.css'
8
+ import './styles/css/main.css'
9
+ // generate user styles
10
+ import '/@valaxyjs/styles'
11
+ import 'uno.css'
12
+
1
13
  import type { ViteSSGContext } from 'vite-ssg'
2
14
  import { ViteSSG } from 'vite-ssg'
3
15
 
@@ -9,16 +21,6 @@ import AppLink from './components/AppLink.vue'
9
21
 
10
22
  import App from './App.vue'
11
23
 
12
- // reset styles
13
- // import '@unocss/reset/tailwind.css'
14
- // https://unocss.dev/guide/style-reset#tailwind-compat
15
- // minus the background color override for buttons to avoid conflicts with UI frameworks
16
- import '@unocss/reset/tailwind-compat.css'
17
-
18
- // generate user styles
19
- import '/@valaxyjs/styles'
20
- import 'uno.css'
21
-
22
24
  import setupMain from './setup/main'
23
25
  import { setupValaxyDevTools } from './utils/dev'
24
26
 
@@ -20,9 +20,7 @@ export default function setupMain(ctx: ViteSSGContext, config: ComputedRef<Valax
20
20
  const injection_arg = ctx
21
21
 
22
22
  installValaxy(ctx, config)
23
-
24
23
  installSchema(ctx)
25
-
26
24
  installPinia(ctx)
27
25
  installNprogress(ctx)
28
26
 
@@ -0,0 +1,3 @@
1
+ declare module 'virtual:valaxy-theme' {
2
+ export default any
3
+ }
@@ -1,19 +1,35 @@
1
1
  import { acceptHMRUpdate, defineStore } from 'pinia'
2
2
  import { useToggle } from '@vueuse/core'
3
3
  import { ref } from 'vue'
4
+ import { useMobile, useThemeConfig, useValaxyDark } from 'valaxy'
4
5
 
6
+ /**
7
+ * Global store for users
8
+ * @example
9
+ * ```ts
10
+ * import { useAppStore } from 'valaxy'
11
+ * const appStore = useAppStore()
12
+ * ```
13
+ */
5
14
  export const useAppStore = defineStore('app', () => {
15
+ const themeConfig = useThemeConfig()
16
+ const { isDark, toggleDark, toggleDarkWithTransition, themeColor } = useValaxyDark(themeConfig.value.valaxyDarkOptions)
17
+
18
+ const isMobile = useMobile()
6
19
  const showLoading = ref(true)
7
20
 
8
- const [isSidebarOpen, toggleSidebar] = useToggle(false)
9
21
  // right sidebar with toc
10
22
  const [isRightSidebarOpen, toggleRightSidebar] = useToggle(false)
11
23
 
12
24
  return {
13
- showLoading,
25
+ isMobile,
26
+ // for dark
27
+ isDark,
28
+ themeColor,
29
+ toggleDark,
30
+ toggleDarkWithTransition,
14
31
 
15
- isSidebarOpen,
16
- toggleSidebar,
32
+ showLoading,
17
33
 
18
34
  isRightSidebarOpen,
19
35
  toggleRightSidebar,
@@ -0,0 +1,19 @@
1
+ :root {
2
+ --va-c-bg: #ffffff;
3
+ --va-c-bg-light: #ffffff;
4
+ --va-c-bg-dark: #fafafa;
5
+ --va-c-bg-opacity: rgba(255, 255, 255, 0.8);
6
+ --va-c-bg-soft: #f9f9f9;
7
+ --va-c-bg-alt: #f9f9f9;
8
+ --va-c-bg-mute: #f1f1f1;
9
+ }
10
+
11
+ html.dark {
12
+ --va-c-bg: #1b1b1f;
13
+ --va-c-bg-light: #202127;
14
+ --va-c-bg-dark: #1a1a1a;
15
+ --va-c-bg-opacity: rgba(0, 0, 0, 0.8);
16
+ --va-c-bg-alt: #161618;
17
+ --va-c-bg-soft: #202127;
18
+ --va-c-bg-mute: #2f2f2f;
19
+ }
@@ -6,7 +6,7 @@ body,
6
6
  line-height: 2;
7
7
  }
8
8
 
9
- body {
9
+ html {
10
10
  background-color: var(--va-c-bg);
11
11
  }
12
12
 
@@ -39,7 +39,7 @@ $c-primary: #0078e7 !default;
39
39
  }
40
40
 
41
41
  // dark
42
- .dark {
42
+ html.dark {
43
43
  color-scheme: dark;
44
44
 
45
45
  @include set-css-var-from-map(palette.$dark);
@@ -4,7 +4,6 @@ $c-primary: #0078e7 !default;
4
4
 
5
5
  // global css
6
6
  @use "./global/reset.scss" as *;
7
- @use "./global/index.scss" as *;
8
7
  @use "./global/nprogress.scss" as *;
9
8
 
10
9
  // https://github.com/valaxyjs/css-i18n
@@ -46,15 +46,6 @@ $light: map.merge(
46
46
 
47
47
  "border-color": #222,
48
48
 
49
- "c-bg": white,
50
- "c-bg-light": white,
51
- "c-bg-dark": #fafafa,
52
- "c-bg-opacity": rgba(255, 255, 255 , 0.8),
53
-
54
- "c-bg-soft": #f9f9f9,
55
- "c-bg-alt": #f9f9f9,
56
- "c-bg-mute": #f1f1f1,
57
-
58
49
  "c-text": #333,
59
50
  "c-text-light": #555,
60
51
  "c-text-lighter": #666,
@@ -71,15 +62,6 @@ $dark: map.merge(
71
62
  (
72
63
  "border-color": #e6e6e6,
73
64
 
74
- "c-bg": #1b1b1f,
75
- "c-bg-light": #202127,
76
- "c-bg-dark": #1a1a1a,
77
- "c-bg-opacity": rgba(0, 0, 0, 0.8),
78
-
79
- "c-bg-alt": #161618,
80
- "c-bg-soft": #202127,
81
- "c-bg-mute": #2f2f2f,
82
-
83
65
  "c-text": #f2f2f2,
84
66
  "c-text-light": #ddd,
85
67
  "c-text-lighter": #eee,
@@ -1,3 +1,5 @@
1
+ import type { Router } from 'vue-router'
2
+
1
3
  export interface ScrollToOptions {
2
4
  /**
3
5
  * 平滑滚动
@@ -43,3 +45,49 @@ export function scrollTo(el: HTMLElement, hash: string, options: Partial<ScrollT
43
45
  }
44
46
  }
45
47
  }
48
+
49
+ /**
50
+ * @description Intercept click events and handle offset positions for jump links on the same page
51
+ * @description:zh-CN 拦截点击事件,处理同一页面下跳转链接的偏移位置
52
+ * @param router Vue Router
53
+ */
54
+ export function onClickHref(router: Router) {
55
+ // to extract
56
+ // click title scroll
57
+ window.addEventListener(
58
+ 'click',
59
+ async (e) => {
60
+ const link = (e.target as Element).closest('a')
61
+ if (link) {
62
+ const { protocol, hostname, pathname, hash, target } = link
63
+ const currentUrl = window.location
64
+ const extMatch = pathname.match(/\.\w+$/)
65
+ // only intercept inbound links
66
+ if (
67
+ !e.ctrlKey
68
+ && !e.shiftKey
69
+ && !e.altKey
70
+ && !e.metaKey
71
+ && target !== '_blank'
72
+ && protocol === currentUrl.protocol
73
+ && hostname === currentUrl.hostname
74
+ && !(extMatch && extMatch[0] !== '.html')
75
+ ) {
76
+ if (pathname === currentUrl.pathname) {
77
+ e.preventDefault()
78
+ // scroll between hash anchors in the same page
79
+ if (hash && hash !== currentUrl.hash) {
80
+ await router.push({ hash: decodeURIComponent(hash) })
81
+
82
+ // use smooth scroll when clicking on header anchor links
83
+ scrollTo(link, hash, {
84
+ smooth: link.classList.contains('header-anchor'),
85
+ })
86
+ }
87
+ }
88
+ }
89
+ }
90
+ },
91
+ { capture: true },
92
+ )
93
+ }