@sugarat/theme 0.1.14 → 0.1.15
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 +12 -1
- package/node.js +12 -15
- package/package.json +1 -1
- package/src/components/BlogApp.vue +1 -1
- package/src/components/BlogArticleAnalyze.vue +1 -1
- package/src/components/BlogSearch.vue +79 -29
- package/src/composables/config/blog.ts +8 -4
- package/src/composables/config/index.ts +17 -2
- package/src/index.ts +1 -0
- package/src/node.ts +16 -15
- package/src/utils/index.ts +1 -1
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?:
|
|
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("
|
|
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
|
@@ -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
|
|
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"
|
|
15
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
132
|
-
|
|
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
|
|
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
|
-
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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:
|
|
279
|
-
|
|
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
|
|
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
|
-
|
|
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?:
|
|
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
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 (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
]
|
package/src/utils/index.ts
CHANGED
|
@@ -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
|