@sugarat/theme 0.1.14 → 0.1.16

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/node.d.ts CHANGED
@@ -132,6 +132,17 @@ declare namespace Theme {
132
132
  url: string;
133
133
  avatar: string;
134
134
  }
135
+ type SearchConfig = boolean | 'pagefind' | {
136
+ btnPlaceholder?: string;
137
+ placeholder?: string;
138
+ emptyText?: string;
139
+ /**
140
+ * @example
141
+ * 'Total: {{searchResult}} search results.'
142
+ */
143
+ heading?: string;
144
+ mode?: boolean | 'pagefind';
145
+ };
135
146
  interface BlogConfig {
136
147
  blog?: false;
137
148
  pagesData: PageData[];
@@ -139,7 +150,7 @@ declare namespace Theme {
139
150
  author?: string;
140
151
  hotArticle?: HotArticle;
141
152
  home?: HomeBlog;
142
- search?: boolean | 'pagefind';
153
+ search?: SearchConfig;
143
154
  /**
144
155
  * 配置评论
145
156
  * power by https://giscus.app/zh-CN
package/node.js CHANGED
@@ -118,27 +118,15 @@ function getThemeConfig(cfg) {
118
118
  };
119
119
  }).filter((v) => v.meta.layout !== "home");
120
120
  const extraConfig = {};
121
- if (cfg?.search === "pagefind") {
122
- checkKeys.push("head", "vite");
123
- extraConfig.head = [
124
- [
125
- "script",
126
- {},
127
- `import('/_pagefind/pagefind.js')
128
- .then((module) => {
129
- window.__pagefind__ = module
130
- })
131
- .catch(() => {
132
- console.log('not load /_pagefind/pagefind.js')
133
- })`
134
- ]
135
- ];
121
+ if (cfg?.search === "pagefind" || cfg?.search instanceof Object && cfg.search.mode === "pagefind") {
122
+ checkKeys.push("vite");
136
123
  let flag = true;
137
124
  let originLog = null;
138
125
  extraConfig.vite = {
139
126
  plugins: [
140
127
  {
141
128
  name: "@sugarar/theme-plugin-pagefind",
129
+ enforce: "pre",
142
130
  buildEnd() {
143
131
  const { log } = console;
144
132
  if (flag) {
@@ -166,6 +154,15 @@ function getThemeConfig(cfg) {
166
154
  }
167
155
  });
168
156
  }
157
+ },
158
+ transform(code, id) {
159
+ if (id.endsWith("theme-default/Layout.vue")) {
160
+ return code.replace(
161
+ "<VPContent>",
162
+ "<VPContent data-pagefind-body>"
163
+ );
164
+ }
165
+ return code;
169
166
  }
170
167
  }
171
168
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sugarat/theme",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -45,7 +45,7 @@
45
45
  "sass": "^1.56.1",
46
46
  "tsup": " ^6.5.0",
47
47
  "typescript": "^4.8.2",
48
- "vitepress": "1.0.0-alpha.46",
48
+ "vitepress": "1.0.0-alpha.62",
49
49
  "vue": "^3.2.45"
50
50
  },
51
51
  "scripts": {
@@ -17,7 +17,7 @@ const { Layout } = Theme
17
17
  </script>
18
18
 
19
19
  <template>
20
- <Layout data-pagefind-body>
20
+ <Layout>
21
21
  <template #layout-top>
22
22
  <BlogAlert />
23
23
  <BlogPopover />
@@ -104,7 +104,7 @@ const publishDate = computed(() => {
104
104
  })
105
105
 
106
106
  const { theme } = useData<Theme.Config>()
107
- const globalAuthor = computed(() => theme.value.blog.author || '')
107
+ const globalAuthor = computed(() => theme.value.blog?.author || '')
108
108
  const author = computed(
109
109
  () => currentArticle.value?.meta.author || globalAuthor.value
110
110
  )
@@ -11,28 +11,27 @@
11
11
  stroke-linejoin="round"
12
12
  ></path>
13
13
  </svg>
14
- <span class="search-tip">搜索</span>
15
- <span class="metaKey"> ⌘ K </span>
14
+ <span v-if="!isMinimized" class="search-tip">{{
15
+ searchConfig?.btnPlaceholder || '搜索'
16
+ }}</span>
17
+ <span v-if="!isMinimized" class="metaKey"> {{ metaKey }} K </span>
16
18
  </div>
17
19
  <Command.Dialog :visible="searchModal" theme="algolia">
18
20
  <template #header>
19
21
  <Command.Input
20
22
  v-model:value="searchWords"
21
- placeholder="请输入要搜索的内容"
23
+ :placeholder="searchConfig?.placeholder || '请输入要搜素的内容'"
22
24
  />
23
25
  </template>
24
26
  <template #body>
25
27
  <div class="search-dialog">
26
28
  <Command.List>
27
- <Command.Empty v-if="!searchResult.length"
28
- >No results found.</Command.Empty
29
- >
30
- <Command.Group
31
- v-else
32
- :heading="`共:${searchResult.length} 个搜索结果`"
33
- >
29
+ <Command.Empty v-if="!searchResult.length">{{
30
+ searchConfig?.emptyText || 'No results found.'
31
+ }}</Command.Empty>
32
+ <Command.Group v-else :heading="headingText">
34
33
  <Command.Item
35
- v-for="item in showSearchResult"
34
+ v-for="item in searchResult"
36
35
  :data-value="withBase(item.route)"
37
36
  :key="item.route"
38
37
  @select="handleSelect"
@@ -128,27 +127,76 @@
128
127
  </template>
129
128
 
130
129
  <script lang="ts" setup>
131
- import { computed, nextTick, ref, watch } from 'vue'
132
- // @ts-ignore
130
+ // @ts-nocheck
131
+ import { computed, nextTick, ref, watch, onBeforeMount, onMounted } from 'vue'
133
132
  import { Command } from 'vue-command-palette'
134
133
  import { useRoute, useRouter, withBase } from 'vitepress'
135
- import { useMagicKeys } from '@vueuse/core'
134
+ import { useMagicKeys, useWindowSize } from '@vueuse/core'
136
135
  import { formatDate } from '../utils'
137
136
  import { useArticles, useBlogConfig } from '../composables/config/blog'
138
137
  import { Theme } from '../composables/config'
139
138
  import LogoPagefind from './LogoPagefind.vue'
140
139
 
141
- const { search: openSearch = true } = useBlogConfig()
140
+ const windowSize = useWindowSize()
142
141
 
142
+ const isMinimized = computed(() => windowSize.width.value < 760)
143
+ const flexValue = computed(() => (isMinimized.value ? 0 : 1))
144
+ const { search: searchConfig } = useBlogConfig()
145
+
146
+ const headingText = computed(() => {
147
+ return searchConfig?.heading
148
+ ? searchConfig.heading.replace(
149
+ /\{\{searchResult\}\}/,
150
+ searchResult.value.length
151
+ )
152
+ : `共: ${searchResult.value.length} 个搜索结果`
153
+ })
154
+ const openSearch = computed(() =>
155
+ searchConfig instanceof Object
156
+ ? searchConfig.mode ?? true
157
+ : searchConfig || true
158
+ )
159
+
160
+ const addInlineScript = () => {
161
+ const scriptText = `import('/_pagefind/pagefind.js')
162
+ .then((module) => {
163
+ window.__pagefind__ = module
164
+ })
165
+ .catch(() => {
166
+ console.log('not load /_pagefind/pagefind.js')
167
+ })`
168
+ const inlineScript = document.createElement('script')
169
+ inlineScript.innerHTML = scriptText
170
+ document.head.appendChild(inlineScript)
171
+ }
172
+
173
+ onBeforeMount(() => {
174
+ if (openSearch.value === 'pagefind') {
175
+ addInlineScript()
176
+ }
177
+ })
178
+
179
+ const metaKey = ref('')
180
+ onMounted(() => {
181
+ metaKey.value = /(Mac|iPhone|iPod|iPad)/i.test(navigator?.platform)
182
+ ? '⌘'
183
+ : 'Ctrl'
184
+ })
143
185
  const searchModal = ref(false)
144
186
  const searchWords = ref('')
145
187
  const docs = useArticles()
146
188
 
147
189
  const keys = useMagicKeys()
148
190
  const CmdK = keys['Meta+K']
191
+ const CtrlK = keys['Ctrl+K']
149
192
  // eslint-disable-next-line dot-notation, prefer-destructuring
150
193
  const Escape = keys['Escape']
151
194
 
195
+ watch(CtrlK, (v) => {
196
+ if (v) {
197
+ searchModal.value = true
198
+ }
199
+ })
152
200
  watch(CmdK, (v) => {
153
201
  if (v) {
154
202
  searchModal.value = true
@@ -191,7 +239,7 @@ const inlineSearch = () => {
191
239
  watch(
192
240
  () => searchWords.value,
193
241
  async () => {
194
- if (openSearch === 'pagefind') {
242
+ if (openSearch.value === 'pagefind') {
195
243
  // dev-server兜底
196
244
  // @ts-ignore
197
245
  if (!window?.__pagefind__?.search) {
@@ -252,15 +300,17 @@ watch(
252
300
  }
253
301
  }
254
302
  )
255
- const pageSize = ref(6)
256
- const currentPage = ref(0)
257
- const showSearchResult = computed(() => {
258
- // 合法性处理
259
- const pageIdx =
260
- currentPage.value % Math.ceil(searchResult.value.length / pageSize.value)
261
- const startIdx = pageIdx * pageSize.value
262
- return searchResult.value.slice(startIdx, startIdx + pageSize.value)
263
- })
303
+
304
+ // 搜索结果分页?
305
+ // const pageSize = ref(6)
306
+ // const currentPage = ref(0)
307
+ // const showSearchResult = computed(() => {
308
+ // // 合法性处理
309
+ // const pageIdx =
310
+ // currentPage.value % Math.ceil(searchResult.value.length / pageSize.value)
311
+ // const startIdx = pageIdx * pageSize.value
312
+ // return searchResult.value.slice(startIdx, startIdx + pageSize.value)
313
+ // })
264
314
 
265
315
  const router = useRouter()
266
316
  const route = useRoute()
@@ -275,8 +325,9 @@ const handleSelect = (target: any) => {
275
325
 
276
326
  <style lang="scss" scoped>
277
327
  .blog-search {
278
- flex: 1;
279
- margin-left: 10px;
328
+ flex: v-bind(flexValue);
329
+ display: flex;
330
+ padding-left: 32px;
280
331
  .nav-search-btn-wait {
281
332
  cursor: pointer;
282
333
  display: flex;
@@ -284,7 +335,6 @@ const handleSelect = (target: any) => {
284
335
  justify-content: center;
285
336
  padding: 6px;
286
337
  box-sizing: border-box;
287
- width: 120px;
288
338
 
289
339
  .metaKey {
290
340
  margin-left: 10px;
@@ -292,7 +342,7 @@ const handleSelect = (target: any) => {
292
342
  }
293
343
 
294
344
  &:hover {
295
- border: 1px solid #409eff;
345
+ border: 1px solid var(--vp-c-brand);
296
346
  border-radius: 6px;
297
347
  }
298
348
 
@@ -51,7 +51,7 @@ export function useConfig() {
51
51
  }
52
52
 
53
53
  export function useBlogConfig() {
54
- return inject(configSymbol)!.value.blog
54
+ return inject(configSymbol)!.value.blog!
55
55
  }
56
56
 
57
57
  export function useBlogThemeMode() {
@@ -81,9 +81,13 @@ export function useCurrentArticle() {
81
81
  const route = useRoute()
82
82
 
83
83
  const docs = computed(() => blogConfig.config?.blog?.pagesData)
84
- const currentArticle = computed(() =>
85
- docs.value?.find((v) => v.route === route.path.replace(/.html$/, ''))
86
- )
84
+ const currentArticle = computed(() => {
85
+ const currentPath = route.path.replace(/.html$/, '')
86
+ return docs.value?.find((v) =>
87
+ // 兼容中文路径
88
+ [currentPath, decodeURIComponent(currentPath)].includes(v.route)
89
+ )
90
+ })
87
91
 
88
92
  return currentArticle
89
93
  }
@@ -144,6 +144,21 @@ export namespace Theme {
144
144
  url: string
145
145
  avatar: string
146
146
  }
147
+ export type SearchConfig =
148
+ | boolean
149
+ | 'pagefind'
150
+ | {
151
+ btnPlaceholder?: string
152
+ placeholder?: string
153
+ emptyText?: string
154
+ /**
155
+ * @example
156
+ * 'Total: {{searchResult}} search results.'
157
+ */
158
+ heading?: string
159
+ mode?: boolean | 'pagefind'
160
+ }
161
+
147
162
  export interface BlogConfig {
148
163
  blog?: false
149
164
  pagesData: PageData[]
@@ -151,8 +166,8 @@ export namespace Theme {
151
166
  author?: string
152
167
  hotArticle?: HotArticle
153
168
  home?: HomeBlog
154
- // TODO: 本地全文搜索定制 pagefind || minisearch
155
- search?: boolean | 'pagefind'
169
+ // TODO: 本地全文搜索定制 pagefind || minisearch || flexsearch
170
+ search?: SearchConfig
156
171
  /**
157
172
  * 配置评论
158
173
  * power by https://giscus.app/zh-CN
package/src/index.ts CHANGED
@@ -17,6 +17,7 @@ export const BlogTheme: Theme = {
17
17
  ...DefaultTheme,
18
18
  Layout: withConfigProvider(BlogApp),
19
19
  enhanceApp(ctx) {
20
+ // TODO: 优化到自定义组件中注册
20
21
  ctx.app.component('TimelinePage', TimelinePage)
21
22
  }
22
23
  }
package/src/node.ts CHANGED
@@ -86,27 +86,18 @@ export function getThemeConfig(cfg?: Partial<Theme.BlogConfig>) {
86
86
 
87
87
  const extraConfig: any = {}
88
88
 
89
- if (cfg?.search === 'pagefind') {
90
- checkKeys.push('head', 'vite')
91
- extraConfig.head = [
92
- [
93
- 'script',
94
- {},
95
- `import('/_pagefind/pagefind.js')
96
- .then((module) => {
97
- window.__pagefind__ = module
98
- })
99
- .catch(() => {
100
- console.log('not load /_pagefind/pagefind.js')
101
- })`
102
- ]
103
- ]
89
+ if (
90
+ cfg?.search === 'pagefind' ||
91
+ (cfg?.search instanceof Object && cfg.search.mode === 'pagefind')
92
+ ) {
93
+ checkKeys.push('vite')
104
94
  let flag = true
105
95
  let originLog: any = null
106
96
  extraConfig.vite = {
107
97
  plugins: [
108
98
  {
109
99
  name: '@sugarar/theme-plugin-pagefind',
100
+ enforce: 'pre',
110
101
  buildEnd() {
111
102
  const { log } = console
112
103
  // TODO: hack
@@ -136,6 +127,16 @@ export function getThemeConfig(cfg?: Partial<Theme.BlogConfig>) {
136
127
  }
137
128
  })
138
129
  }
130
+ },
131
+ // 添加检索的内容标识
132
+ transform(code: string, id: string) {
133
+ if (id.endsWith('theme-default/Layout.vue')) {
134
+ return code.replace(
135
+ '<VPContent>',
136
+ '<VPContent data-pagefind-body>'
137
+ )
138
+ }
139
+ return code
139
140
  }
140
141
  }
141
142
  ]
@@ -115,7 +115,7 @@ ul {
115
115
  }
116
116
 
117
117
  body {
118
- background: var(--app-bg);
118
+ // background: var(--app-bg);
119
119
  }
120
120
 
121
121
  div [command-dialog-mask] {
@@ -39,7 +39,7 @@ export function isCurrentWeek(date: Date, target?: Date) {
39
39
  }
40
40
 
41
41
  export function formatShowDate(date: Date | string) {
42
- const source = +new Date(date)
42
+ const source = date ? +new Date(date) : +new Date()
43
43
  const now = +new Date()
44
44
  const diff = now - source
45
45
  const oneSeconds = 1000