@sugarat/theme 0.5.11 → 0.5.12-beta.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 (49) hide show
  1. package/node.d.ts +2 -4
  2. package/node.js +206 -156
  3. package/node.mjs +205 -154
  4. package/package.json +10 -15
  5. package/src/components/Alert.vue +269 -0
  6. package/src/components/Avatar.vue +65 -0
  7. package/src/components/BlogAlert.vue +8 -8
  8. package/src/components/BlogApp.vue +5 -8
  9. package/src/components/BlogArticleAnalyze.vue +99 -66
  10. package/src/components/BlogAuthor.vue +13 -15
  11. package/src/components/BlogBackToTop.vue +21 -24
  12. package/src/components/BlogButtonAfterArticle.vue +12 -15
  13. package/src/components/BlogCommentWrapper.vue +34 -41
  14. package/src/components/BlogDocCover.vue +1 -1
  15. package/src/components/BlogFooter.vue +26 -32
  16. package/src/components/BlogFriendLink.vue +91 -73
  17. package/src/components/BlogHomeBanner.vue +25 -31
  18. package/src/components/BlogHomeHeaderAvatar.vue +16 -23
  19. package/src/components/BlogHomeInfo.vue +2 -4
  20. package/src/components/BlogHomeOverview.vue +12 -15
  21. package/src/components/BlogHomeTags.vue +22 -31
  22. package/src/components/BlogHotArticle.vue +69 -80
  23. package/src/components/BlogImagePreview.vue +3 -3
  24. package/src/components/BlogItem.vue +14 -23
  25. package/src/components/BlogList.vue +15 -19
  26. package/src/components/BlogRecommendArticle.vue +56 -72
  27. package/src/components/BlogSidebar.vue +1 -1
  28. package/src/components/Button.vue +150 -0
  29. package/src/components/Carousel.vue +249 -0
  30. package/src/components/CarouselItem.vue +139 -0
  31. package/src/components/CommentArtalk.vue +1 -1
  32. package/src/components/Image.vue +33 -0
  33. package/src/components/ImageViewer.vue +407 -0
  34. package/src/components/Pagination.vue +369 -0
  35. package/src/components/Tag.vue +144 -0
  36. package/src/components/UserWorks.vue +132 -175
  37. package/src/composables/config/blog.ts +6 -1
  38. package/src/composables/config/index.ts +2 -2
  39. package/src/index.ts +12 -19
  40. package/src/node.ts +0 -3
  41. package/src/styles/el-base.css +340 -0
  42. package/src/styles/{index.scss → index.css} +56 -91
  43. package/src/utils/client/index.ts +17 -0
  44. package/src/utils/node/mdPlugins.ts +1 -1
  45. package/src/utils/node/theme.ts +5 -2
  46. package/src/utils/node/vitePlugins.ts +51 -18
  47. package/src/styles/scss/algolia.scss +0 -231
  48. package/src/styles/scss/global.scss +0 -156
  49. package/src/styles/scss/highlight.scss +0 -12
@@ -36,22 +36,20 @@ useHoverSpin(imgRef, home?.value?.hoverSpin)
36
36
  </div>
37
37
  </template>
38
38
 
39
- <style scoped lang="scss">
39
+ <style scoped>
40
40
  .blog-author {
41
41
  margin-bottom: 20px;
42
-
43
- img {
44
- display: block;
45
- margin: 10px auto;
46
- width: 100px;
47
- height: 100px;
48
- border-radius: 50%;
49
- background-color: rgba(var(--bg-gradient-home));
50
- cursor: pointer;
51
- }
52
-
53
- p {
54
- text-align: center;
55
- }
42
+ }
43
+ .blog-author img {
44
+ display: block;
45
+ margin: 10px auto;
46
+ width: 100px;
47
+ height: 100px;
48
+ border-radius: 50%;
49
+ background-color: rgba(var(--bg-gradient-home));
50
+ cursor: pointer;
51
+ }
52
+ .blog-author p {
53
+ text-align: center;
56
54
  }
57
55
  </style>
@@ -40,7 +40,7 @@ const iconSVGStr = computed(() => backToTopConfig?.value?.icon)
40
40
  </div>
41
41
  </template>
42
42
 
43
- <style lang="scss" scoped>
43
+ <style scoped>
44
44
  .back-to-top {
45
45
  position: fixed;
46
46
  width: v-bind(docWidth);
@@ -52,29 +52,26 @@ const iconSVGStr = computed(() => backToTopConfig?.value?.icon)
52
52
  display: flex;
53
53
  justify-content: right;
54
54
  z-index: 200;
55
-
56
- &:hover {
57
- opacity: 1;
58
- }
59
-
60
- .icon-wrapper {
61
- cursor: pointer;
62
- border-radius: 50%;
63
- position: relative;
64
- right: -80px;
65
- background-color: var(--vp-c-bg);
66
- box-shadow: var(--box-shadow);
67
- padding: 4px;
68
- display: flex;
69
- align-items: center;
70
- justify-content: center;
71
- background-color: var(--vp-c-brand-soft);
72
- color: var(--vp-c-brand-1);
73
-
74
- &:hover {
75
- box-shadow: var(--box-shadow-hover);
76
- }
77
- }
55
+ }
56
+ .back-to-top:hover {
57
+ opacity: 1;
58
+ }
59
+ .back-to-top .icon-wrapper {
60
+ cursor: pointer;
61
+ border-radius: 50%;
62
+ position: relative;
63
+ right: -80px;
64
+ background-color: var(--vp-c-bg);
65
+ box-shadow: var(--box-shadow);
66
+ padding: 4px;
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ background-color: var(--vp-c-brand-soft);
71
+ color: var(--vp-c-brand-1);
72
+ }
73
+ .back-to-top .icon-wrapper:hover {
74
+ box-shadow: var(--box-shadow-hover);
78
75
  }
79
76
 
80
77
  @media screen and (max-width: 1200px) {
@@ -1,8 +1,8 @@
1
1
  <script lang="ts" setup>
2
- import { ElButton } from 'element-plus'
3
2
  import { computed, ref, watch } from 'vue'
4
3
  import { useButtonAfterConfig } from '../composables/config/blog'
5
4
  import { aliPaySVG, weChatPaySVG } from '../constants/svg'
5
+ import Button from './Button.vue'
6
6
 
7
7
  const buttonAfterArticleConfig = useButtonAfterConfig()
8
8
 
@@ -36,27 +36,27 @@ function toggleContent() {
36
36
 
37
37
  <template>
38
38
  <div v-if="buttonAfterArticleConfig" class="appreciation-container">
39
- <ElButton :size="buttonAfterArticleConfig.size || 'default'" class="content-button" :type="showContent ? 'danger' : 'primary'" @click="toggleContent">
39
+ <Button :size="buttonAfterArticleConfig.size || 'default'" class="content-button" :type="showContent ? 'danger' : 'primary'" @click="toggleContent">
40
40
  <span class="content-icon" v-html="svg" />
41
41
  {{ showContent ? buttonAfterArticleConfig.closeTitle : buttonAfterArticleConfig.openTitle }}
42
- </ElButton>
42
+ </Button>
43
43
  <transition name="content">
44
44
  <div v-if="showContent" class="content-container" v-html="buttonAfterArticleConfig.content" />
45
45
  </transition>
46
46
  </div>
47
47
  </template>
48
48
 
49
- <style scoped lang="scss">
49
+ <style scoped>
50
+ @charset "UTF-8";
50
51
  .appreciation-container {
51
52
  text-align: center;
52
53
  padding: 20px;
53
54
  font-size: 14px;
54
55
  color: #606266;
55
-
56
- :deep(.el-button.el-button--primary){
57
- background-color: var(--vp-c-brand-2);
58
- border-color: var(--vp-c-brand-2);
59
- }
56
+ }
57
+ .appreciation-container :deep(.sugar-button.sugar-button--primary) {
58
+ background-color: var(--vp-c-brand-2);
59
+ border-color: var(--vp-c-brand-2);
60
60
  }
61
61
 
62
62
  .content-container {
@@ -65,9 +65,9 @@ function toggleContent() {
65
65
  justify-content: center;
66
66
  align-items: center;
67
67
  margin-top: 20px;
68
- :deep(img){
69
- height: 260px;
70
- }
68
+ }
69
+ .content-container :deep(img) {
70
+ height: 260px;
71
71
  }
72
72
 
73
73
  .content-icon {
@@ -94,18 +94,15 @@ function toggleContent() {
94
94
  from {
95
95
  opacity: 0;
96
96
  }
97
-
98
97
  to {
99
98
  opacity: 1;
100
99
  }
101
100
  }
102
-
103
101
  /* 淡出 */
104
102
  @keyframes fadeOut {
105
103
  from {
106
104
  opacity: 1;
107
105
  }
108
-
109
106
  to {
110
107
  opacity: 0;
111
108
  }
@@ -52,7 +52,7 @@ const labelText = computed(() => {
52
52
  </div>
53
53
  </template>
54
54
 
55
- <style scoped lang="scss">
55
+ <style scoped>
56
56
  .comment-btn-wrapper {
57
57
  position: fixed;
58
58
  width: v-bind(docWidth);
@@ -64,49 +64,42 @@ const labelText = computed(() => {
64
64
  display: flex;
65
65
  justify-content: right;
66
66
  z-index: 200;
67
-
68
- &:hover {
69
- opacity: 1;
70
- }
71
-
72
- .icon-wrapper,
73
- .icon-wrapper-text {
74
- cursor: pointer;
75
- border-radius: 50%;
76
- position: relative;
77
- right: -80px;
78
- background-color: var(--vp-c-bg);
79
- box-shadow: var(--box-shadow);
80
- padding: 4px;
81
- display: flex;
82
- align-items: center;
83
- justify-content: center;
84
- background-color: var(--vp-c-brand-soft);
85
- color: var(--vp-c-brand-1);
86
-
87
- &:hover {
88
- box-shadow: var(--box-shadow-hover);
89
- }
90
- }
91
-
92
- .icon-wrapper-text {
93
- border-radius: 2px;
94
- padding: 2px 6px;
95
-
96
- span.text {
97
- font-size: 12px;
98
- margin-left: 4px;
99
- }
100
- }
67
+ }
68
+ .comment-btn-wrapper:hover {
69
+ opacity: 1;
70
+ }
71
+ .comment-btn-wrapper .icon-wrapper,
72
+ .comment-btn-wrapper .icon-wrapper-text {
73
+ cursor: pointer;
74
+ border-radius: 50%;
75
+ position: relative;
76
+ right: -80px;
77
+ background-color: var(--vp-c-bg);
78
+ box-shadow: var(--box-shadow);
79
+ padding: 4px;
80
+ display: flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ background-color: var(--vp-c-brand-soft);
84
+ color: var(--vp-c-brand-1);
85
+ }
86
+ .comment-btn-wrapper .icon-wrapper:hover,
87
+ .comment-btn-wrapper .icon-wrapper-text:hover {
88
+ box-shadow: var(--box-shadow-hover);
89
+ }
90
+ .comment-btn-wrapper .icon-wrapper-text {
91
+ border-radius: 2px;
92
+ padding: 2px 6px;
93
+ }
94
+ .comment-btn-wrapper .icon-wrapper-text span.text {
95
+ font-size: 12px;
96
+ margin-left: 4px;
101
97
  }
102
98
 
103
99
  @media screen and (max-width: 1200px) {
104
- .comment-btn-wrapper {
105
-
106
- .icon-wrapper,
107
- .icon-wrapper-text {
108
- position: static;
109
- }
100
+ .comment-btn-wrapper .icon-wrapper,
101
+ .comment-btn-wrapper .icon-wrapper-text {
102
+ position: static;
110
103
  }
111
104
  }
112
105
  </style>
@@ -19,7 +19,7 @@ const hiddenCover = computed(
19
19
  <img v-if="cover && !hiddenCover" class="blog-doc-cover" :src="realCover">
20
20
  </template>
21
21
 
22
- <style lang="scss" scoped>
22
+ <style scoped>
23
23
  img.blog-doc-cover.blog-doc-cover.blog-doc-cover {
24
24
  width: 100%;
25
25
  object-fit: cover;
@@ -115,20 +115,19 @@ const renderData = computed(() => {
115
115
  </footer>
116
116
  </template>
117
117
 
118
- <style lang="scss" scoped>
118
+ <style scoped>
119
119
  footer.blog-footer {
120
120
  text-align: center;
121
121
  position: relative;
122
122
  border-top: 1px solid var(--vp-c-gutter);
123
123
  padding: 20px 12px;
124
124
  background-color: var(--vp-c-bg);
125
-
126
- p {
127
- line-height: 24px;
128
- font-size: 14px;
129
- font-weight: 500;
130
- color: var(--vp-c-text-2);
131
- }
125
+ }
126
+ footer.blog-footer p {
127
+ line-height: 24px;
128
+ font-size: 14px;
129
+ font-weight: 500;
130
+ color: var(--vp-c-text-2);
132
131
  }
133
132
 
134
133
  .footer-item-list {
@@ -143,33 +142,28 @@ footer.blog-footer {
143
142
  align-items: center;
144
143
  }
145
144
  }
146
-
147
145
  .footer-item {
148
146
  display: flex;
149
147
  align-items: center;
150
148
  margin: 0 8px;
151
-
152
- i {
153
- margin-right: 4px;
154
- font-style: normal;
155
- }
156
-
157
- i :deep(svg) {
158
- fill: var(--vp-c-text-2);
159
- width: 16px;
160
- height: 16px;
161
- }
162
-
163
- i :deep(img) {
164
- width: 16px;
165
- height: 16px;
166
- }
167
-
168
- a:hover {
169
- color: var(--vp-c-brand-1);
170
- text-decoration: underline;
171
- text-decoration-color: var(--vp-c-brand-1);
172
- text-decoration-style: dashed;
173
- }
149
+ }
150
+ .footer-item i {
151
+ margin-right: 4px;
152
+ font-style: normal;
153
+ }
154
+ .footer-item i :deep(svg) {
155
+ fill: var(--vp-c-text-2);
156
+ width: 16px;
157
+ height: 16px;
158
+ }
159
+ .footer-item i :deep(img) {
160
+ width: 16px;
161
+ height: 16px;
162
+ }
163
+ .footer-item a:hover {
164
+ color: var(--vp-c-brand-1);
165
+ text-decoration: underline;
166
+ text-decoration-color: var(--vp-c-brand-1);
167
+ text-decoration-style: dashed;
174
168
  }
175
169
  </style>
@@ -1,12 +1,11 @@
1
1
  <script lang="ts" setup>
2
- import { ElAvatar } from 'element-plus'
3
2
  import { useDark, useIntervalFn } from '@vueuse/core'
4
- import { computed, onMounted, onUnmounted, ref } from 'vue'
5
- import Swiper from 'swiper'
3
+ import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
6
4
  import { useFriendData } from '../composables/config/blog'
7
- import { getImageUrl, shuffleArray } from '../utils/client'
5
+ import { getImageUrl } from '../utils/client'
8
6
  import type { Theme } from '../'
9
7
  import { friendLinkSvgStr } from '../constants/svg'
8
+ import Avatar from './Avatar.vue'
10
9
 
11
10
  const isDark = useDark({
12
11
  storageKey: 'vitepress-theme-appearance'
@@ -37,10 +36,10 @@ const openScroll = computed(() => {
37
36
 
38
37
  const friendList = computed(() => {
39
38
  const data = [...friendConfig.value.list]
40
- // 简单的随机打乱
41
- if (friendConfig.value.random) {
42
- data.splice(0, data.length, ...shuffleArray(data))
43
- }
39
+ // 简单的随机打乱,在数据导入侧打乱,避免SSG与CSR内容不一致
40
+ // if (friendConfig.value.random) {
41
+ // data.splice(0, data.length, ...shuffleArray(data))
42
+ // }
44
43
 
45
44
  // 展示个数限制,删除多余的
46
45
  if (scrollSpeed.value === 0 && limit.value) {
@@ -71,25 +70,55 @@ const containerHeight = computed(() => {
71
70
  return scrollWrapperHeight.value ? `${scrollWrapperHeight.value}px` : 'auto'
72
71
  })
73
72
 
74
- const swiper = ref<Swiper>()
75
- const { resume, pause } = useIntervalFn(() => {
76
- swiper.value?.slideNext()
77
- }, scrollSpeed.value)
73
+ const currentIndex = ref(0)
74
+ const isTransitioning = ref(false)
78
75
 
79
- onMounted(() => {
80
- pause()
76
+ const displayList = computed(() => {
81
77
  if (openScroll.value) {
82
- // eslint-disable-next-line no-new
83
- swiper.value = new Swiper('.scroll-wrapper', {
84
- direction: 'vertical',
85
- slidesPerView: limit.value,
86
- loop: true,
87
- })
78
+ return [...friendList.value, ...friendList.value.slice(0, limit.value)]
79
+ }
80
+ return friendList.value
81
+ })
82
+
83
+ const listStyle = computed(() => {
84
+ const translate = -1 * currentIndex.value * cardHeight
85
+ return {
86
+ transform: `translateY(${translate}px)`,
87
+ transition: isTransitioning.value ? 'transform 0.5s ease-in-out' : 'none'
88
+ }
89
+ })
90
+
91
+ const { resume, pause } = useIntervalFn(() => {
92
+ if (!openScroll.value)
93
+ return
94
+
95
+ currentIndex.value++
96
+ isTransitioning.value = true
97
+
98
+ if (currentIndex.value === friendList.value.length) {
99
+ setTimeout(() => {
100
+ isTransitioning.value = false
101
+ currentIndex.value = 0
102
+ }, 500)
103
+ }
104
+ }, scrollSpeed)
105
+
106
+ watch(openScroll, (val) => {
107
+ if (val) {
88
108
  resume()
89
109
  }
110
+ else {
111
+ pause()
112
+ currentIndex.value = 0
113
+ isTransitioning.value = false
114
+ }
115
+ })
116
+
117
+ onMounted(() => {
118
+ if (openScroll.value)
119
+ resume()
90
120
  })
91
121
 
92
- // TODO: SSR渲染支持
93
122
  onUnmounted(() => {
94
123
  pause()
95
124
  })
@@ -107,10 +136,10 @@ onUnmounted(() => {
107
136
  height: containerHeight,
108
137
  }"
109
138
  >
110
- <ol class="friend-list swiper-wrapper">
111
- <li v-for=" (v, idx) in friendList" :key="idx" class="swiper-slide">
139
+ <ol class="friend-list" :style="listStyle">
140
+ <li v-for="(v, idx) in displayList" :key="idx" class="scroll-item">
112
141
  <a :href="v.url" target="_blank">
113
- <ElAvatar :size="50" :src="v.avatar" :alt="v.alt" />
142
+ <Avatar :size="50" :src="v.avatar" :alt="v.alt" />
114
143
  <div class="info-wrapper">
115
144
  <span class="nickname">{{ v.nickname }}</span>
116
145
  <p class="des">{{ v.des }}</p>
@@ -122,7 +151,7 @@ onUnmounted(() => {
122
151
  </div>
123
152
  </template>
124
153
 
125
- <style lang="scss" scoped>
154
+ <style scoped>
126
155
  .card {
127
156
  position: relative;
128
157
  margin: 0 auto 10px;
@@ -135,10 +164,9 @@ onUnmounted(() => {
135
164
  transition: all 0.3s;
136
165
  background-color: rgba(var(--bg-gradient));
137
166
  display: flex;
138
-
139
- &:hover {
140
- box-shadow: var(--box-shadow-hover);
141
- }
167
+ }
168
+ .card:hover {
169
+ box-shadow: var(--box-shadow-hover);
142
170
  }
143
171
 
144
172
  .card-header {
@@ -146,12 +174,11 @@ onUnmounted(() => {
146
174
  width: 100%;
147
175
  justify-content: space-between;
148
176
  align-items: center;
149
-
150
- .title {
151
- font-size: 12px;
152
- display: flex;
153
- align-items: center;
154
- }
177
+ }
178
+ .card-header .title {
179
+ font-size: 12px;
180
+ display: flex;
181
+ align-items: center;
155
182
  }
156
183
 
157
184
  .friend-wrapper {
@@ -170,45 +197,36 @@ onUnmounted(() => {
170
197
  margin: 0;
171
198
  padding: 10px 10px 0 0px;
172
199
  width: 100%;
173
-
174
200
  position: relative;
175
201
  width: 100%;
176
-
177
- li {
178
- box-sizing: border-box;
179
- padding: 0 5px;
180
- height: 76px;
181
- .el-avatar {
182
- min-width: 50px;
183
- }
184
-
185
- a {
186
- display: flex;
187
- align-items: center;
188
- }
189
-
190
- div {
191
- padding-left: 10px;
192
- }
193
-
194
- .info-wrapper {
195
- display: flex;
196
- flex-direction: column;
197
- overflow: hidden;
198
- }
199
-
200
- .nickname {
201
- font-size: 16px;
202
- font-weight: 450;
203
- }
204
-
205
- .des {
206
- color: var(--vp-c-text-2);
207
- font-size: 14px;
208
- overflow: hidden;
209
- white-space: nowrap;
210
- text-overflow: ellipsis;
211
- }
212
- }
202
+ }
203
+ .friend-list li {
204
+ box-sizing: border-box;
205
+ padding: 0 5px;
206
+ height: 76px;
207
+ cursor: pointer;
208
+ }
209
+ .friend-list li a {
210
+ display: flex;
211
+ align-items: center;
212
+ }
213
+ .friend-list li div {
214
+ padding-left: 10px;
215
+ }
216
+ .friend-list li .info-wrapper {
217
+ display: flex;
218
+ flex-direction: column;
219
+ overflow: hidden;
220
+ }
221
+ .friend-list li .nickname {
222
+ font-size: 16px;
223
+ font-weight: 450;
224
+ }
225
+ .friend-list li .des {
226
+ color: var(--vp-c-text-2);
227
+ font-size: 14px;
228
+ overflow: hidden;
229
+ white-space: nowrap;
230
+ text-overflow: ellipsis;
213
231
  }
214
232
  </style>
@@ -85,28 +85,26 @@ async function changeSlogan() {
85
85
  </div>
86
86
  </template>
87
87
 
88
- <style lang="scss" scoped>
88
+ <style scoped>
89
89
  h1 {
90
90
  text-align: center;
91
- .name {
92
- transition: all 0.25s ease-in-out 0.04s;
93
- transform: translateY(0px);
94
- opacity: 1;
95
- font-weight: bold;
96
- margin: 0 auto;
97
- font-size: 36px;
98
- }
99
-
100
- .motto {
101
- position: relative;
102
- bottom: 0px;
103
- font-size: 14px;
104
- margin-left: 10px;
105
-
106
- &::before {
107
- content: '- ';
108
- }
109
- }
91
+ }
92
+ h1 .name {
93
+ transition: all 0.25s ease-in-out 0.04s;
94
+ transform: translateY(0px);
95
+ opacity: 1;
96
+ font-weight: bold;
97
+ margin: 0 auto;
98
+ font-size: 36px;
99
+ }
100
+ h1 .motto {
101
+ position: relative;
102
+ bottom: 0px;
103
+ font-size: 14px;
104
+ margin-left: 10px;
105
+ }
106
+ h1 .motto::before {
107
+ content: "- ";
110
108
  }
111
109
 
112
110
  @media screen and (max-width: 500px) {
@@ -114,28 +112,24 @@ h1 {
114
112
  display: none;
115
113
  }
116
114
  }
117
-
118
115
  @keyframes fade-in {
119
116
  0% {
120
117
  opacity: 0;
121
118
  }
122
-
123
119
  100% {
124
120
  opacity: 1;
125
121
  }
126
122
  }
127
-
128
123
  .inspiring-wrapper {
129
124
  margin: 16px 0;
130
125
  height: 32px;
131
126
  width: auto;
132
-
133
- h2 {
134
- animation: fade-in 0.5s ease-in-out;
135
- cursor: pointer;
136
- text-align: center;
137
- font-size: 20px;
138
- line-height: 1.6;
139
- }
127
+ }
128
+ .inspiring-wrapper h2 {
129
+ animation: fade-in 0.5s ease-in-out;
130
+ cursor: pointer;
131
+ text-align: center;
132
+ font-size: 20px;
133
+ line-height: 1.6;
140
134
  }
141
135
  </style>