@sugarat/theme 0.1.8 → 0.1.10

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
@@ -42,7 +42,11 @@ declare namespace Theme {
42
42
  /**
43
43
  * 文章首页置顶
44
44
  */
45
- top: number;
45
+ top?: number;
46
+ /**
47
+ * 手动控制相关文章列表的顺序
48
+ */
49
+ recommend?: number | false;
46
50
  /**
47
51
  * 时间线
48
52
  */
@@ -135,7 +139,7 @@ declare namespace Theme {
135
139
  author?: string;
136
140
  hotArticle?: HotArticle;
137
141
  home?: HomeBlog;
138
- search?: boolean;
142
+ search?: boolean | 'pagefind';
139
143
  /**
140
144
  * 配置评论
141
145
  * power by https://giscus.app/zh-CN
@@ -166,7 +170,7 @@ declare function getThemeConfig(cfg?: Partial<Theme.BlogConfig>): {
166
170
  author?: string | undefined;
167
171
  hotArticle?: Theme.HotArticle | undefined;
168
172
  home?: Theme.HomeBlog | undefined;
169
- search?: boolean | undefined;
173
+ search?: boolean | "pagefind" | undefined;
170
174
  comment?: false | Theme.GiscusConfig | undefined;
171
175
  recommend?: Theme.RecommendArticle | undefined;
172
176
  article?: Theme.ArticleConfig | undefined;
package/node.js CHANGED
@@ -183,6 +183,60 @@ function getTextSummary(text, count = 100) {
183
183
  return clearMatterContent(text).match(/^# ([\s\S]+)/m)?.[1]?.replace(/#/g, "")?.replace(/!\[.*?\]\(.*?\)/g, "")?.replace(/\[(.*?)\]\(.*?\)/g, "$1")?.replace(/\*\*(.*?)\*\*/g, "$1")?.split("\n")?.filter((v) => !!v)?.slice(1)?.join("\n")?.replace(/>(.*)/, "")?.slice(0, count);
184
184
  }
185
185
  function defineConfig(config) {
186
+ if (config?.themeConfig?.blog?.search === "pagefind") {
187
+ config.head = (config.head || []).concat([
188
+ [
189
+ "script",
190
+ {},
191
+ `import('/_pagefind/pagefind.js')
192
+ .then((module) => {
193
+ window.__pagefind__ = module
194
+ })
195
+ .catch(() => {
196
+ console.log('not load /_pagefind/pagefind.js')
197
+ })`
198
+ ]
199
+ ]);
200
+ let flag = true;
201
+ let originLog = null;
202
+ config.vite = {
203
+ ...config.vite,
204
+ plugins: [
205
+ ...config.vite?.plugins || [],
206
+ {
207
+ name: "@sugarar/theme-plugin-pagefind",
208
+ buildEnd() {
209
+ const { log } = console;
210
+ if (flag) {
211
+ flag = false;
212
+ originLog = log;
213
+ Object.defineProperty(console, "log", {
214
+ value() {
215
+ if (`${arguments[0]}`.includes("build complete")) {
216
+ console.log = originLog;
217
+ setTimeout(() => {
218
+ originLog();
219
+ originLog("=== pagefind: https://pagefind.app/ ===");
220
+ const command = `npx pagefind --source ${import_path.default.join(
221
+ process.argv.slice(2)?.[1] || ".",
222
+ ".vitepress/dist"
223
+ )}`;
224
+ originLog(command);
225
+ originLog();
226
+ (0, import_child_process.execSync)(command, {
227
+ stdio: "inherit"
228
+ });
229
+ }, 100);
230
+ }
231
+ return log.apply(this, arguments);
232
+ }
233
+ });
234
+ }
235
+ }
236
+ }
237
+ ]
238
+ };
239
+ }
186
240
  return config;
187
241
  }
188
242
  // Annotate the CommonJS export names for ESM import in node:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sugarat/theme",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -52,6 +52,6 @@
52
52
  "build": "npm run build:node && npm run build:docs",
53
53
  "build:docs": "vitepress build demo",
54
54
  "build:node": "npx tsup src/node.ts --dts --out-dir=./",
55
- "serve": "npm run build && vitepress serve demo"
55
+ "serve": "vitepress serve demo"
56
56
  }
57
57
  }
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="global-alert" v-if="show">
2
+ <div class="global-alert" v-if="show" data-pagefind-ignore="all">
3
3
  <el-alert
4
4
  :title="alertProps?.title"
5
5
  :type="alertProps?.type"
@@ -17,7 +17,7 @@ const { Layout } = Theme
17
17
  </script>
18
18
 
19
19
  <template>
20
- <Layout>
20
+ <Layout data-pagefind-body>
21
21
  <template #layout-top>
22
22
  <BlogAlert />
23
23
  <BlogPopover />
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="doc-analyze" v-if="showAnalyze">
2
+ <div class="doc-analyze" v-if="showAnalyze" data-pagefind-ignore="all">
3
3
  <span>
4
4
  <el-icon><EditPen /></el-icon>
5
5
  字数:{{ wordCount }} 个字
@@ -1,5 +1,10 @@
1
1
  <template>
2
- <div class="comment" v-if="show" id="giscus-comment">
2
+ <div
3
+ class="comment"
4
+ v-if="show"
5
+ id="giscus-comment"
6
+ data-pagefind-ignore="all"
7
+ >
3
8
  <el-affix
4
9
  :class="{ hidden: !showCommnetAffix }"
5
10
  class="comment-btn"
@@ -6,7 +6,7 @@ import BlogFriendLink from './BlogFriendLink.vue'
6
6
  </script>
7
7
 
8
8
  <template>
9
- <div class="blog-info">
9
+ <div class="blog-info" data-pagefind-ignore="all">
10
10
  <!-- 统计数据,日后支持,点击筛选出左侧的数据 -->
11
11
  <BlogHomeOverview />
12
12
 
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="card tags" v-if="tags.length">
2
+ <div class="card tags" v-if="tags.length" data-pagefind-ignore="all">
3
3
  <!-- 头部 -->
4
4
  <div class="card-header">
5
5
  <span class="title">🏷 标签</span>
@@ -1,5 +1,9 @@
1
1
  <template>
2
- <div class="card recommend" v-if="recommendList.length || empty">
2
+ <div
3
+ class="card recommend"
4
+ v-if="recommendList.length || empty"
5
+ data-pagefind-ignore="all"
6
+ >
3
7
  <!-- 头部 -->
4
8
  <div class="card-header">
5
9
  <span class="title">{{ title }}</span>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <ul>
2
+ <ul data-pagefind-ignore="all">
3
3
  <li v-for="v in currentWikiData" :key="v.route">
4
4
  <blog-item
5
5
  :route="v.route"
@@ -44,8 +44,8 @@ const activeTag = useActiveTag()
44
44
  const activeTagLabel = computed(() => activeTag.value.label)
45
45
 
46
46
  const wikiList = computed(() => {
47
- const topList = docs.value.filter((v) => v.meta.top)
48
- topList.sort((a, b) => a.meta.top - b.meta.top)
47
+ const topList = docs.value.filter((v) => !!v.meta.top)
48
+ topList.sort((a, b) => a.meta!.top - b.meta!.top)
49
49
  const data = docs.value.filter(
50
50
  (v) => v.meta.date && v.meta.title && !v.meta.top && !v.meta.hidden
51
51
  )
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="theme-blog-popover" v-show="show">
2
+ <div class="theme-blog-popover" v-show="show" data-pagefind-ignore="all">
3
3
  <div class="header">
4
4
  <div class="title-wrapper">
5
5
  <el-icon size="20px"><Flag /></el-icon>
@@ -1,5 +1,9 @@
1
1
  <template>
2
- <div class="card recommend" v-if="recommendList.length || emptyText">
2
+ <div
3
+ class="card recommend"
4
+ v-if="recommendList.length || emptyText"
5
+ data-pagefind-ignore="all"
6
+ >
3
7
  <!-- 头部 -->
4
8
  <div class="card-header">
5
9
  <span class="title">{{ title }}</span>
@@ -66,9 +70,16 @@ const recommendList = computed(() => {
66
70
  .filter((v) => !!v.meta.title)
67
71
  // 过滤掉自己
68
72
  .filter((v) => v.route !== route.path.replace(/.html$/, ''))
73
+ // 过滤掉不需要展示的
74
+ .filter((v) => v.meta.recommend !== false)
69
75
 
70
- origin.sort((a, b) => +new Date(b.meta.date) - +new Date(a.meta.date))
71
- return origin
76
+ const topList = origin.filter((v) => v.meta?.recommend)
77
+ topList.sort((a, b) => Number(a.meta.recommend) - Number(b.meta.recommend))
78
+
79
+ const normalList = origin.filter((v) => !v.meta?.recommend)
80
+ normalList.sort((a, b) => +new Date(b.meta.date) - +new Date(a.meta.date))
81
+
82
+ return topList.concat(normalList)
72
83
  })
73
84
  const currentPage = ref(1)
74
85
  const changePage = () => {
@@ -128,7 +139,7 @@ const showChangeBtn = computed(() => {
128
139
  font-size: 14px;
129
140
  color: var(--description-font-color);
130
141
  font-weight: 600;
131
- margin: 6px 12px 10px 0;
142
+ margin: 6px 8px 10px 0;
132
143
  width: 18px;
133
144
  height: 18px;
134
145
  line-height: 18px;
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="blog-search" v-if="openSearch">
2
+ <div class="blog-search" v-if="openSearch" data-pagefind-ignore="all">
3
3
  <div class="nav-search-btn-wait" @click="searchModal = true">
4
4
  <el-icon size="22px">
5
5
  <Search />
@@ -47,9 +47,7 @@
47
47
  {{ formatDate(item.meta.date, 'yyyy-MM-dd') }}</span
48
48
  >
49
49
  </div>
50
- <div class="des">
51
- {{ item.meta.description }}
52
- </div>
50
+ <div class="des" v-html="item.meta.description"></div>
53
51
  </a>
54
52
  </el-card>
55
53
  </li>
@@ -73,6 +71,7 @@ import {
73
71
  import { useWindowSize } from '@vueuse/core'
74
72
  import { formatDate } from '../utils'
75
73
  import { useArticles, useBlogConfig } from '../composables/config/blog'
74
+ import { Theme } from '../composables/config'
76
75
 
77
76
  const { search: openSearch = true } = useBlogConfig()
78
77
 
@@ -96,16 +95,56 @@ watch(
96
95
 
97
96
  const docs = useArticles()
98
97
 
99
- const searchResult = computed(() => {
100
- if (!searchWords.value) return []
101
- const result = docs.value.filter((v) =>
98
+ const searchResult = ref<Theme.PageData[]>([])
99
+ const inlineSearch = () => {
100
+ if (!searchWords.value) {
101
+ searchResult.value = []
102
+ return
103
+ }
104
+ searchResult.value = docs.value.filter((v) =>
102
105
  `${v.meta.description}${v.meta.title}`.includes(searchWords.value)
103
106
  )
104
- result.sort((a, b) => {
107
+ searchResult.value.sort((a, b) => {
105
108
  return +new Date(b.meta.date) - +new Date(a.meta.date)
106
109
  })
107
- return result
108
- })
110
+ }
111
+ watch(
112
+ () => searchWords.value,
113
+ () => {
114
+ if (openSearch === 'pagefind') {
115
+ // dev-server兜底
116
+ // @ts-ignore
117
+ if (!window?.__pagefind__?.search) {
118
+ inlineSearch()
119
+ return
120
+ }
121
+ // @ts-ignore
122
+ window?.__pagefind__
123
+ ?.search?.(searchWords.value)
124
+ .then(async (search: any) => {
125
+ const result = await Promise.all(
126
+ search.results.map((v: any) => v.data())
127
+ )
128
+ searchResult.value = []
129
+ docs.value.forEach((v) => {
130
+ const match = result.find((r) => r.url.startsWith(v.route))
131
+ if (match) {
132
+ searchResult.value.push({
133
+ ...v,
134
+ meta: {
135
+ ...v.meta,
136
+ description: match.excerpt
137
+ }
138
+ })
139
+ }
140
+ })
141
+ })
142
+ } else {
143
+ inlineSearch()
144
+ }
145
+ }
146
+ )
147
+
109
148
  const pageSize = ref(6)
110
149
  const currentPage = ref(0)
111
150
  const showSearchResult = computed(() => {
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="sidebar"><BlogRecommendArticle /></div>
2
+ <div class="sidebar" data-pagefind-ignore="all"><BlogRecommendArticle /></div>
3
3
  </template>
4
4
 
5
5
  <script lang="ts" setup>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <div>时间线页面</div>
3
+ </template>
4
+
5
+ <script lang="ts" setup></script>
6
+
7
+ <style lang="scss"></style>
@@ -48,7 +48,11 @@ export namespace Theme {
48
48
  /**
49
49
  * 文章首页置顶
50
50
  */
51
- top: number
51
+ top?: number
52
+ /**
53
+ * 手动控制相关文章列表的顺序
54
+ */
55
+ recommend?: number | false
52
56
  // TODO: 待开发
53
57
  /**
54
58
  * 时间线
@@ -148,7 +152,7 @@ export namespace Theme {
148
152
  hotArticle?: HotArticle
149
153
  home?: HomeBlog
150
154
  // TODO: 本地全文搜索定制 pagefind || minisearch
151
- search?: boolean
155
+ search?: boolean | 'pagefind'
152
156
  /**
153
157
  * 配置评论
154
158
  * power by https://giscus.app/zh-CN
package/src/index.ts CHANGED
@@ -10,9 +10,15 @@ import DefaultTheme from 'vitepress/theme'
10
10
  import BlogApp from './components/BlogApp.vue'
11
11
  import { withConfigProvider } from './composables/config/blog'
12
12
 
13
+ // page
14
+ import TimelinePage from './components/TimelinePage.vue'
15
+
13
16
  export const BlogTheme: Theme = {
14
17
  ...DefaultTheme,
15
- Layout: withConfigProvider(BlogApp)
18
+ Layout: withConfigProvider(BlogApp),
19
+ enhanceApp(ctx) {
20
+ ctx.app.component('TimelinePage', TimelinePage)
21
+ }
16
22
  }
17
23
 
18
24
  export * from './composables/config/index'
package/src/node.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /* eslint-disable prefer-rest-params */
1
2
  import glob from 'fast-glob'
2
3
  import matter from 'gray-matter'
3
4
  import fs from 'fs'
@@ -188,5 +189,61 @@ function getTextSummary(text: string, count = 100) {
188
189
  }
189
190
 
190
191
  export function defineConfig(config: UserConfig<Theme.Config>) {
192
+ if (config?.themeConfig?.blog?.search === 'pagefind') {
193
+ config.head = (config.head || []).concat([
194
+ [
195
+ 'script',
196
+ {},
197
+ `import('/_pagefind/pagefind.js')
198
+ .then((module) => {
199
+ window.__pagefind__ = module
200
+ })
201
+ .catch(() => {
202
+ console.log('not load /_pagefind/pagefind.js')
203
+ })`
204
+ ]
205
+ ])
206
+ let flag = true
207
+ let originLog: any = null
208
+ config.vite = {
209
+ ...config.vite,
210
+ plugins: [
211
+ ...(config.vite?.plugins || []),
212
+ {
213
+ name: '@sugarar/theme-plugin-pagefind',
214
+ buildEnd() {
215
+ const { log } = console
216
+ // TODO: hack
217
+ if (flag) {
218
+ flag = false
219
+ originLog = log
220
+ Object.defineProperty(console, 'log', {
221
+ value() {
222
+ if (`${arguments[0]}`.includes('build complete')) {
223
+ console.log = originLog
224
+ setTimeout(() => {
225
+ originLog()
226
+ originLog('=== pagefind: https://pagefind.app/ ===')
227
+ const command = `npx pagefind --source ${path.join(
228
+ process.argv.slice(2)?.[1] || '.',
229
+ '.vitepress/dist'
230
+ )}`
231
+ originLog(command)
232
+ originLog()
233
+ execSync(command, {
234
+ stdio: 'inherit'
235
+ })
236
+ }, 100)
237
+ }
238
+ // @ts-ignore
239
+ return log.apply(this, arguments)
240
+ }
241
+ })
242
+ }
243
+ }
244
+ }
245
+ ]
246
+ }
247
+ }
191
248
  return config
192
249
  }