@sugarat/theme 0.1.49 → 0.1.50

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.
@@ -1,51 +1,9 @@
1
- <template>
2
- <a class="blog-item" :href="withBase(route)">
3
- <i class="pin" v-if="!!pin"></i>
4
- <!-- 标题 -->
5
- <p class="title" v-if="inMobile">{{ title }}</p>
6
- <div class="info-container">
7
- <!-- 左侧信息 -->
8
- <div class="info-part">
9
- <!-- 标题 -->
10
- <p class="title" v-if="!inMobile">{{ title }}</p>
11
- <!-- 简短描述 -->
12
- <p class="description" v-if="!descriptionHTML && !!description">
13
- {{ description }}
14
- </p>
15
- <template v-if="descriptionHTML">
16
- <div class="description-html" v-html="descriptionHTML"></div>
17
- </template>
18
- <!-- 底部补充描述 -->
19
- <div class="badge-list" v-if="!inMobile">
20
- <span class="split" v-if="author">{{ author }}</span>
21
- <span class="split">{{ showTime }}</span>
22
- <span class="split" v-if="tag?.length">{{ tag.join(' · ') }}</span>
23
- </div>
24
- </div>
25
- <!-- 右侧封面图 -->
26
- <div
27
- v-if="cover"
28
- class="cover-img"
29
- :style="`background-image: url(${cover});`"
30
- ></div>
31
- </div>
32
- <!-- 底部补充描述 -->
33
- <div class="badge-list" v-if="inMobile">
34
- <span class="split" v-if="author">{{ author }}</span>
35
- <span class="split">{{ showTime }}</span>
36
- <span class="split" v-if="tag?.length">{{ tag.join(' · ') }}</span>
37
- </div>
38
- </a>
39
- </template>
40
-
41
1
  <script lang="ts" setup>
42
2
  import { withBase } from 'vitepress'
43
3
  import { computed } from 'vue'
44
4
  import { useWindowSize } from '@vueuse/core'
45
5
  import { formatShowDate } from '../utils/client'
46
6
 
47
- const { width } = useWindowSize()
48
- const inMobile = computed(() => width.value <= 500)
49
7
  const props = defineProps<{
50
8
  route: string
51
9
  title: string
@@ -58,7 +16,8 @@ const props = defineProps<{
58
16
  cover?: string | boolean
59
17
  pin?: number
60
18
  }>()
61
-
19
+ const { width } = useWindowSize()
20
+ const inMobile = computed(() => width.value <= 500)
62
21
  const showTime = computed(() => {
63
22
  return formatShowDate(props.date)
64
23
  })
@@ -77,6 +36,46 @@ const showTime = computed(() => {
77
36
  // }
78
37
  </script>
79
38
 
39
+ <template>
40
+ <a class="blog-item" :href="withBase(route)">
41
+ <i v-if="!!pin" class="pin" />
42
+ <!-- 标题 -->
43
+ <p v-if="inMobile" class="title">{{ title }}</p>
44
+ <div class="info-container">
45
+ <!-- 左侧信息 -->
46
+ <div class="info-part">
47
+ <!-- 标题 -->
48
+ <p v-if="!inMobile" class="title">{{ title }}</p>
49
+ <!-- 简短描述 -->
50
+ <p v-if="!descriptionHTML && !!description" class="description">
51
+ {{ description }}
52
+ </p>
53
+ <template v-if="descriptionHTML">
54
+ <div class="description-html" v-html="descriptionHTML" />
55
+ </template>
56
+ <!-- 底部补充描述 -->
57
+ <div v-if="!inMobile" class="badge-list">
58
+ <span v-if="author" class="split">{{ author }}</span>
59
+ <span class="split">{{ showTime }}</span>
60
+ <span v-if="tag?.length" class="split">{{ tag.join(' · ') }}</span>
61
+ </div>
62
+ </div>
63
+ <!-- 右侧封面图 -->
64
+ <div
65
+ v-if="cover"
66
+ class="cover-img"
67
+ :style="`background-image: url(${cover});`"
68
+ />
69
+ </div>
70
+ <!-- 底部补充描述 -->
71
+ <div v-if="inMobile" class="badge-list">
72
+ <span v-if="author" class="split">{{ author }}</span>
73
+ <span class="split">{{ showTime }}</span>
74
+ <span v-if="tag?.length" class="split">{{ tag.join(' · ') }}</span>
75
+ </div>
76
+ </a>
77
+ </template>
78
+
80
79
  <style lang="scss" scoped>
81
80
  .blog-item .pin {
82
81
  position: absolute;
@@ -1,49 +1,16 @@
1
- <template>
2
- <ul data-pagefind-ignore="all">
3
- <li v-for="v in currentWikiData" :key="v.route">
4
- <blog-item
5
- :route="v.route"
6
- :title="v.meta.title"
7
- :description="v.meta.description"
8
- :description-h-t-m-l="v.meta.descriptionHTML"
9
- :date="v.meta.date"
10
- :tag="v.meta.tag"
11
- :cover="v.meta.cover"
12
- :author="v.meta.author || globalAuthor"
13
- :pin="v.meta.top"
14
- />
15
- </li>
16
- </ul>
17
- <!-- 解决element-ui bug -->
18
- <ClientOnly>
19
- <div class="el-pagination-wrapper">
20
- <el-pagination
21
- v-if="wikiList.length >= pageSize"
22
- small
23
- background
24
- :default-current-page="1"
25
- :current-page="currentPage"
26
- @update:current-page="handleUpdatePageNum"
27
- :page-size="pageSize"
28
- :total="filterData.length"
29
- layout="prev, pager, next, jumper"
30
- />
31
- </div>
32
- </ClientOnly>
33
- </template>
34
1
  <script setup lang="ts">
35
2
  import { computed, watch } from 'vue'
36
3
  import { ElPagination } from 'element-plus'
37
4
  import { useData, useRouter } from 'vitepress'
38
5
  import { useBrowserLocation } from '@vueuse/core'
39
- import BlogItem from './BlogItem.vue'
40
6
  import {
41
- useArticles,
42
7
  useActiveTag,
8
+ useArticles,
43
9
  useBlogConfig,
44
10
  useCurrentPageNum
45
11
  } from '../composables/config/blog'
46
- import { Theme } from '../composables/config'
12
+ import type { Theme } from '../composables/config'
13
+ import BlogItem from './BlogItem.vue'
47
14
 
48
15
  const { theme, frontmatter } = useData<Theme.Config>()
49
16
  const globalAuthor = computed(() => theme.value.blog?.author || '')
@@ -54,22 +21,23 @@ const activeTag = useActiveTag()
54
21
  const activeTagLabel = computed(() => activeTag.value.label)
55
22
 
56
23
  const wikiList = computed(() => {
57
- const topList = docs.value.filter((v) => !v.meta.hidden && !!v.meta.top)
24
+ const topList = docs.value.filter(v => !v.meta.hidden && !!v.meta.top)
58
25
  topList.sort((a, b) => {
59
26
  const aTop = a?.meta?.top
60
27
  const bTop = b?.meta.top
61
28
  return Number(aTop) - Number(bTop)
62
29
  })
63
30
  const data = docs.value.filter(
64
- (v) => v.meta.date && v.meta.title && !v.meta.top && !v.meta.hidden
31
+ v => v.meta.date && v.meta.title && !v.meta.top && !v.meta.hidden
65
32
  )
66
33
  data.sort((a, b) => +new Date(b.meta.date) - +new Date(a.meta.date))
67
34
  return topList.concat(data)
68
35
  })
69
36
 
70
37
  const filterData = computed(() => {
71
- if (!activeTagLabel.value) return wikiList.value
72
- return wikiList.value.filter((v) =>
38
+ if (!activeTagLabel.value)
39
+ return wikiList.value
40
+ return wikiList.value.filter(v =>
73
41
  v.meta?.tag?.includes(activeTagLabel.value)
74
42
  )
75
43
  })
@@ -88,7 +56,7 @@ const currentWikiData = computed(() => {
88
56
  const router = useRouter()
89
57
  const location = useBrowserLocation()
90
58
  const queryPageNumKey = 'pageNum'
91
- const handleUpdatePageNum = (current: number) => {
59
+ function handleUpdatePageNum(current: number) {
92
60
  if (currentPage.value === current) {
93
61
  return
94
62
  }
@@ -108,7 +76,8 @@ watch(
108
76
  const { searchParams } = new URL(location.value.href)
109
77
  if (searchParams.has(queryPageNumKey)) {
110
78
  currentPage.value = Number(searchParams.get(queryPageNumKey))
111
- } else {
79
+ }
80
+ else {
112
81
  currentPage.value = 1
113
82
  }
114
83
  }
@@ -118,6 +87,41 @@ watch(
118
87
  }
119
88
  )
120
89
  </script>
90
+
91
+ <template>
92
+ <ul data-pagefind-ignore="all">
93
+ <li v-for="v in currentWikiData" :key="v.route">
94
+ <BlogItem
95
+ :route="v.route"
96
+ :title="v.meta.title"
97
+ :description="v.meta.description"
98
+ :description-h-t-m-l="v.meta.descriptionHTML"
99
+ :date="v.meta.date"
100
+ :tag="v.meta.tag"
101
+ :cover="v.meta.cover"
102
+ :author="v.meta.author || globalAuthor"
103
+ :pin="v.meta.top"
104
+ />
105
+ </li>
106
+ </ul>
107
+ <!-- 解决element-ui bug -->
108
+ <ClientOnly>
109
+ <div class="el-pagination-wrapper">
110
+ <ElPagination
111
+ v-if="wikiList.length >= pageSize"
112
+ small
113
+ background
114
+ :default-current-page="1"
115
+ :current-page="currentPage"
116
+ :page-size="pageSize"
117
+ :total="filterData.length"
118
+ layout="prev, pager, next, jumper"
119
+ @update:current-page="handleUpdatePageNum"
120
+ />
121
+ </div>
122
+ </ClientOnly>
123
+ </template>
124
+
121
125
  <style lang="scss" scoped>
122
126
  .el-pagination-wrapper {
123
127
  :deep(.el-pagination li.is-active.number) {
@@ -1,39 +1,7 @@
1
- <template>
2
- <div class="theme-blog-popover" v-show="show" data-pagefind-ignore="all">
3
- <div class="header">
4
- <div class="title-wrapper">
5
- <el-icon size="20px"><Flag /></el-icon>
6
- <span class="title">{{ popoverProps?.title }}</span>
7
- </div>
8
- <el-icon @click="show = false" class="close-icon" size="20px"
9
- ><CircleCloseFilled
10
- /></el-icon>
11
- </div>
12
- <div class="body content" v-if="bodyContent.length">
13
- <PopoverValue v-for="(v, idx) in bodyContent" :key="idx" :item="v">
14
- {{ v.type !== 'image' ? v.content : '' }}
15
- </PopoverValue>
16
- <hr v-if="footerContent.length" />
17
- </div>
18
- <div class="footer content">
19
- <PopoverValue v-for="(v, idx) in footerContent" :key="idx" :item="v">
20
- {{ v.type !== 'image' ? v.content : '' }}
21
- </PopoverValue>
22
- </div>
23
- </div>
24
- <div
25
- class="theme-blog-popover-close"
26
- v-show="!show && (popoverProps?.reopen ?? true) && popoverProps?.title"
27
- @click="show = true"
28
- >
29
- <el-icon size="20px"><Flag /></el-icon>
30
- </div>
31
- </template>
32
-
33
1
  <script lang="ts" setup>
34
- import { ElIcon, ElButton } from 'element-plus'
35
- import { Flag, CircleCloseFilled } from '@element-plus/icons-vue'
36
- import { computed, onMounted, ref, h } from 'vue'
2
+ import { ElButton, ElIcon } from 'element-plus'
3
+ import { CircleCloseFilled, Flag } from '@element-plus/icons-vue'
4
+ import { computed, h, onMounted, ref } from 'vue'
37
5
  import type { BlogPopover } from '@sugarat/theme'
38
6
  import { parseStringStyle } from '@vue/shared'
39
7
  import { useBlogConfig } from '../composables/config/blog'
@@ -77,10 +45,8 @@ onMounted(() => {
77
45
  }
78
46
  })
79
47
 
80
- const PopoverValue = (
81
- props: { key: number; item: BlogPopover.Value },
82
- { slots }: any
83
- ) => {
48
+ function PopoverValue(props: { key: number; item: BlogPopover.Value },
49
+ { slots }: any) {
84
50
  const { key, item } = props
85
51
  if (item.type === 'title') {
86
52
  return h(
@@ -130,6 +96,42 @@ const PopoverValue = (
130
96
  }
131
97
  </script>
132
98
 
99
+ <template>
100
+ <div v-show="show" class="theme-blog-popover" data-pagefind-ignore="all">
101
+ <div class="header">
102
+ <div class="title-wrapper">
103
+ <ElIcon size="20px">
104
+ <Flag />
105
+ </ElIcon>
106
+ <span class="title">{{ popoverProps?.title }}</span>
107
+ </div>
108
+ <ElIcon class="close-icon" size="20px" @click="show = false">
109
+ <CircleCloseFilled />
110
+ </ElIcon>
111
+ </div>
112
+ <div v-if="bodyContent.length" class="body content">
113
+ <PopoverValue v-for="(v, idx) in bodyContent" :key="idx" :item="v">
114
+ {{ v.type !== 'image' ? v.content : '' }}
115
+ </PopoverValue>
116
+ <hr v-if="footerContent.length">
117
+ </div>
118
+ <div class="footer content">
119
+ <PopoverValue v-for="(v, idx) in footerContent" :key="idx" :item="v">
120
+ {{ v.type !== 'image' ? v.content : '' }}
121
+ </PopoverValue>
122
+ </div>
123
+ </div>
124
+ <div
125
+ v-show="!show && (popoverProps?.reopen ?? true) && popoverProps?.title"
126
+ class="theme-blog-popover-close"
127
+ @click="show = true"
128
+ >
129
+ <ElIcon size="20px">
130
+ <Flag />
131
+ </ElIcon>
132
+ </div>
133
+ </template>
134
+
133
135
  <style lang="scss" scoped>
134
136
  .theme-blog-popover {
135
137
  width: 258px;
@@ -1,36 +1,5 @@
1
- <template>
2
- <div class="recommend" :class="{ card: sidebarStyle === 'card' }"
3
- v-if="_recommend !== false && (recommendList.length || emptyText)" data-pagefind-ignore="all">
4
- <!-- 头部 -->
5
- <div class="card-header">
6
- <span class="title" v-if="title" v-html="title"></span>
7
- <el-button v-if="showChangeBtn" size="small" type="primary" text @click="changePage">{{ nextText }}</el-button>
8
- </div>
9
- <!-- 文章列表 -->
10
- <ol class="recommend-container" v-if="currentWikiData.length">
11
- <li v-for="(v, idx) in currentWikiData" :key="v.route">
12
- <!-- 序号 -->
13
- <i class="num">{{ startIdx + idx + 1 }}</i>
14
- <!-- 简介 -->
15
- <div class="des">
16
- <!-- title -->
17
- <el-link type="info" class="title" :class="{
18
- current: isCurrentDoc(v.route)
19
- }" :href="v.route">{{ v.meta.title }}</el-link>
20
- <!-- 描述信息 -->
21
- <div class="suffix">
22
- <!-- 日期 -->
23
- <span class="tag">{{ formatShowDate(v.meta.date) }}</span>
24
- </div>
25
- </div>
26
- </li>
27
- </ol>
28
- <div class="empty-text" v-else>{{ emptyText }}</div>
29
- </div>
30
- </template>
31
-
32
1
  <script lang="ts" setup>
33
- import { ref, computed } from 'vue'
2
+ import { computed, ref } from 'vue'
34
3
  import { useRoute, withBase } from 'vitepress'
35
4
  import { ElButton, ElLink } from 'element-plus'
36
5
  import { formatShowDate } from '../utils/client'
@@ -63,43 +32,43 @@ const recommendList = computed(() => {
63
32
  const paths = decodeURIComponent(route.path).split('/')
64
33
 
65
34
  const origin = docs.value
66
- .map((v) => ({ ...v, route: withBase(v.route) }))
35
+ .map(v => ({ ...v, route: withBase(v.route) }))
67
36
  // 过滤出公共路由前缀
68
37
  // 限制为同路由前缀
69
38
  .filter(
70
- (v) =>
71
- v.route.split('/').length === paths.length &&
72
- v.route.startsWith(paths.slice(0, paths.length - 1).join('/'))
39
+ v =>
40
+ v.route.split('/').length === paths.length
41
+ && v.route.startsWith(paths.slice(0, paths.length - 1).join('/'))
73
42
  )
74
43
  // 过滤出带标题的
75
- .filter((v) => !!v.meta.title)
44
+ .filter(v => !!v.meta.title)
76
45
  // 过滤掉自己
77
46
  .filter(
78
- (v) =>
79
- (recommend.value?.showSelf ?? true) ||
80
- v.route !== decodeURIComponent(route.path).replace(/.html$/, '')
47
+ v =>
48
+ (recommend.value?.showSelf ?? true)
49
+ || v.route !== decodeURIComponent(route.path).replace(/.html$/, '')
81
50
  )
82
51
  // 过滤掉不需要展示的
83
- .filter((v) => v.meta.recommend !== false)
84
- .filter((v) => recommend.value?.filter?.(v) ?? true)
52
+ .filter(v => v.meta.recommend !== false)
53
+ .filter(v => recommend.value?.filter?.(v) ?? true)
85
54
 
86
- const topList = origin.filter((v) => v.meta?.recommend)
55
+ const topList = origin.filter(v => v.meta?.recommend)
87
56
  topList.sort((a, b) => Number(a.meta.recommend) - Number(b.meta.recommend))
88
57
 
89
- const normalList = origin.filter((v) => !v.meta?.recommend)
58
+ const normalList = origin.filter(v => !v.meta?.recommend)
90
59
  normalList.sort((a, b) => +new Date(b.meta.date) - +new Date(a.meta.date))
91
60
 
92
61
  return topList.concat(normalList)
93
62
  })
94
63
 
95
- const isCurrentDoc = (value: string) => {
64
+ function isCurrentDoc(value: string) {
96
65
  return value === decodeURIComponent(route.path).replace(/.html$/, '')
97
66
  }
98
67
 
99
68
  const currentPage = ref(1)
100
- const changePage = () => {
101
- const newIdx =
102
- currentPage.value % Math.ceil(recommendList.value.length / pageSize.value)
69
+ function changePage() {
70
+ const newIdx
71
+ = currentPage.value % Math.ceil(recommendList.value.length / pageSize.value)
103
72
  currentPage.value = newIdx + 1
104
73
  }
105
74
  // 当前页开始的序号
@@ -116,6 +85,47 @@ const showChangeBtn = computed(() => {
116
85
  })
117
86
  </script>
118
87
 
88
+ <template>
89
+ <div
90
+ v-if="_recommend !== false && (recommendList.length || emptyText)" class="recommend"
91
+ :class="{ card: sidebarStyle === 'card' }" data-pagefind-ignore="all"
92
+ >
93
+ <!-- 头部 -->
94
+ <div class="card-header">
95
+ <span v-if="title" class="title" v-html="title" />
96
+ <ElButton v-if="showChangeBtn" size="small" type="primary" text @click="changePage">
97
+ {{ nextText }}
98
+ </ElButton>
99
+ </div>
100
+ <!-- 文章列表 -->
101
+ <ol v-if="currentWikiData.length" class="recommend-container">
102
+ <li v-for="(v, idx) in currentWikiData" :key="v.route">
103
+ <!-- 序号 -->
104
+ <i class="num">{{ startIdx + idx + 1 }}</i>
105
+ <!-- 简介 -->
106
+ <div class="des">
107
+ <!-- title -->
108
+ <ElLink
109
+ type="info" class="title" :class="{
110
+ current: isCurrentDoc(v.route),
111
+ }" :href="v.route"
112
+ >
113
+ {{ v.meta.title }}
114
+ </ElLink>
115
+ <!-- 描述信息 -->
116
+ <div class="suffix">
117
+ <!-- 日期 -->
118
+ <span class="tag">{{ formatShowDate(v.meta.date) }}</span>
119
+ </div>
120
+ </div>
121
+ </li>
122
+ </ol>
123
+ <div v-else class="empty-text">
124
+ {{ emptyText }}
125
+ </div>
126
+ </div>
127
+ </template>
128
+
119
129
  <style lang="scss" scoped>
120
130
  .card {
121
131
  position: relative;