@sugarat/theme 0.1.34 → 0.1.36-beta.0

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/README.md CHANGED
@@ -5,11 +5,21 @@
5
5
  ![图片](https://img.cdn.sugarat.top/mdImg/MTY3MzE3MDUxOTMwMw==673170519303)
6
6
 
7
7
  ## Quick Start
8
- 初始化项目模板
9
- ```sh
10
- npx degit ATQQ/sugar-blog/packages/template my-blog-demo
8
+ 创建项目
9
+
10
+ ```bash
11
+ # With PNPM:
12
+ pnpm create @sugarat/theme
13
+
14
+ # With NPM:
15
+ npm create @sugarat/theme@latest
16
+
17
+ # With Yarn:
18
+ yarn create @sugarat/theme
11
19
  ```
12
20
 
21
+ ![](https://img.cdn.sugarat.top/mdImg/MTY4OTQyMDE1NTcxMA==689420155710)
22
+
13
23
  ② 安装依赖
14
24
  ```sh
15
25
  pnpm install
@@ -24,13 +34,14 @@ pnpm dev
24
34
  ```sh
25
35
  pnpm build
26
36
  ```
37
+
38
+ ⑤ 预览构建产物
39
+ ```sh
40
+ pnpm serve
41
+ ```
27
42
  ## Advanced Ssage
28
43
  详细配置见文档 https://theme.sugarat.top
29
44
 
30
- ## Known bugs and workarounds
31
- * `zlib: unexpected end of file:` clearing the cache folder (rm -rf ~/.degit)
32
-
33
-
34
45
  ## Thanks
35
46
  从以下项目中获得了灵感&经验
36
47
  * [vuepress-reco/vuepress-theme-reco-1.x](https://github.com/vuepress-reco/vuepress-theme-reco-1.x)
package/node.d.ts CHANGED
@@ -41,6 +41,7 @@ declare namespace Theme {
41
41
  date: string;
42
42
  tag?: string[];
43
43
  description?: string;
44
+ descriptionHTML?: string;
44
45
  cover?: string;
45
46
  hiddenCover?: boolean;
46
47
  readingTime?: boolean;
@@ -109,7 +110,8 @@ declare namespace Theme {
109
110
  interface HomeBlog {
110
111
  name?: string;
111
112
  motto?: string;
112
- inspiring?: string;
113
+ inspiring?: string | string[];
114
+ inspiringTimeout?: number;
113
115
  pageSize?: number;
114
116
  }
115
117
  interface ArticleConfig {
@@ -247,6 +249,10 @@ declare namespace Theme {
247
249
  blog?: BlogConfig;
248
250
  }
249
251
  interface HomeConfig {
252
+ /**
253
+ * @deprecated
254
+ * 此方法已经废弃,这个定义将在未来某一刻被移除,请为 inspiring 配置数租来实现相同的效果
255
+ */
250
256
  handleChangeSlogan?: (oldSlogan: string) => string | Promise<string>;
251
257
  }
252
258
  }
@@ -256,6 +262,7 @@ declare function getDefaultTitle(content: string): string;
256
262
  declare function clearMatterContent(content: string): string;
257
263
  declare function getFileBirthTime(url: string): string;
258
264
  declare function getGitTimestamp(file: string): Promise<unknown>;
259
- declare function defineConfig(config: UserConfig<Theme.Config>): UserConfig<any>;
265
+ declare function assignMermaid(config: any): void;
266
+ declare function defineConfig(config: UserConfig<Theme.Config>): any;
260
267
 
261
- export { clearMatterContent, defineConfig, getDefaultTitle, getFileBirthTime, getGitTimestamp, getThemeConfig };
268
+ export { assignMermaid, clearMatterContent, defineConfig, getDefaultTitle, getFileBirthTime, getGitTimestamp, getThemeConfig };
package/node.js CHANGED
@@ -26,6 +26,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
26
26
  // src/node.ts
27
27
  var node_exports = {};
28
28
  __export(node_exports, {
29
+ assignMermaid: () => assignMermaid,
29
30
  clearMatterContent: () => clearMatterContent,
30
31
  defineConfig: () => defineConfig,
31
32
  getDefaultTitle: () => getDefaultTitle,
@@ -281,7 +282,7 @@ function getThemeConfig(cfg) {
281
282
  ]);
282
283
  const wordCount = 100;
283
284
  meta.description = meta.description || getTextSummary(fileContent, wordCount);
284
- meta.cover = meta.cover || fileContent.match(/[!]\[.*?\]\((https:\/\/.+)\)/)?.[1] || "";
285
+ meta.cover = meta.cover ?? (fileContent.match(/[!]\[.*?\]\((https:\/\/.+)\)/)?.[1] || "");
285
286
  if (meta.publish === false) {
286
287
  meta.hidden = true;
287
288
  meta.recommend = false;
@@ -346,23 +347,22 @@ function getThemeConfig(cfg) {
346
347
  ]
347
348
  };
348
349
  }
350
+ const markdownPlugin = [];
349
351
  if (cfg?.tabs) {
350
- extraConfig.markdown = {
351
- config(md) {
352
- tabsPlugin(md);
353
- }
354
- };
352
+ markdownPlugin.push(tabsPlugin);
355
353
  }
356
354
  if (cfg) {
357
355
  cfg.mermaid = cfg?.mermaid ?? false;
358
356
  }
359
357
  if (cfg?.mermaid !== false) {
360
- extraConfig.vite = {
361
- ...extraConfig.vite,
362
- resolve: {
363
- alias: {
364
- mermaid: "mermaid/dist/mermaid.esm.mjs"
365
- }
358
+ markdownPlugin.push(import_vitepress_plugin_mermaid.MermaidMarkdown);
359
+ }
360
+ if (markdownPlugin.length) {
361
+ extraConfig.markdown = {
362
+ config(...rest) {
363
+ markdownPlugin.forEach((plugin) => {
364
+ plugin?.(...rest);
365
+ });
366
366
  }
367
367
  };
368
368
  }
@@ -437,6 +437,39 @@ function getGitTimestamp(file) {
437
437
  function getTextSummary(text, count = 100) {
438
438
  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);
439
439
  }
440
+ function assignMermaid(config) {
441
+ if (!config.mermaid)
442
+ return;
443
+ if (!config.vite)
444
+ config.vite = {};
445
+ if (!config.vite.plugins)
446
+ config.vite.plugins = [];
447
+ config.vite.plugins.push((0, import_vitepress_plugin_mermaid.MermaidPlugin)(config.mermaid));
448
+ if (!config.vite.optimizeDeps)
449
+ config.vite.optimizeDeps = {};
450
+ config.vite.optimizeDeps = {
451
+ ...config.vite.optimizeDeps,
452
+ include: [
453
+ "@braintree/sanitize-url",
454
+ "dayjs",
455
+ "debug",
456
+ "cytoscape-cose-bilkent",
457
+ "cytoscape"
458
+ ]
459
+ };
460
+ if (!config.vite.resolve)
461
+ config.vite.resolve = {};
462
+ if (!config.vite.resolve.alias)
463
+ config.vite.resolve.alias = {};
464
+ config.vite.resolve.alias = {
465
+ ...config.vite.resolve.alias,
466
+ "dayjs/plugin/advancedFormat.js": "dayjs/esm/plugin/advancedFormat",
467
+ "dayjs/plugin/customParseFormat.js": "dayjs/esm/plugin/customParseFormat",
468
+ "dayjs/plugin/isoWeek.js": "dayjs/esm/plugin/isoWeek",
469
+ "cytoscape/dist/cytoscape.umd.js": "cytoscape/dist/cytoscape.esm.js",
470
+ mermaid: "mermaid/dist/mermaid.esm.mjs"
471
+ };
472
+ }
440
473
  function defineConfig(config) {
441
474
  if (config.themeConfig?.themeConfig) {
442
475
  config.extends = checkKeys.reduce((pre, key) => {
@@ -450,10 +483,11 @@ function defineConfig(config) {
450
483
  }, 1200);
451
484
  }
452
485
  const extendThemeConfig = config.extends?.themeConfig?.blog;
453
- const resultConfig = extendThemeConfig.mermaid === false ? config : (0, import_vitepress_plugin_mermaid.withMermaid)({
486
+ const resultConfig = extendThemeConfig.mermaid === false ? config : {
454
487
  ...config,
455
488
  mermaid: extendThemeConfig.mermaid === true ? {} : extendThemeConfig.mermaid
456
- });
489
+ };
490
+ assignMermaid(resultConfig);
457
491
  if (!resultConfig.markdown)
458
492
  resultConfig.markdown = {};
459
493
  if (config.extends?.markdown?.config) {
@@ -468,6 +502,7 @@ function defineConfig(config) {
468
502
  }
469
503
  // Annotate the CommonJS export names for ESM import in node:
470
504
  0 && (module.exports = {
505
+ assignMermaid,
471
506
  clearMatterContent,
472
507
  defineConfig,
473
508
  getDefaultTitle,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sugarat/theme",
3
- "version": "0.1.34",
3
+ "version": "0.1.36-beta.0",
4
4
  "description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -10,9 +10,9 @@
10
10
  </div>
11
11
  </template>
12
12
  <script setup lang="ts">
13
- import { computed, ref } from 'vue'
13
+ import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
14
14
  import { useData } from 'vitepress'
15
- import { useHomeConfig, useBlogConfig } from '../composables/config/blog'
15
+ import { useBlogConfig } from '../composables/config/blog'
16
16
 
17
17
  const { site, frontmatter } = useData()
18
18
  const { home } = useBlogConfig()
@@ -21,34 +21,61 @@ const name = computed(
21
21
  () => (frontmatter.value.blog?.name ?? site.value.title) || home?.name || ''
22
22
  )
23
23
  const motto = computed(() => frontmatter.value.blog?.motto || home?.motto || '')
24
- const initInspiring = ref<string>(
25
- frontmatter.value.blog?.inspiring || home?.inspiring || ''
24
+
25
+ const inspiring = ref('')
26
+ const inspiringList = computed<string[]>(() => {
27
+ return [
28
+ ...new Set(
29
+ [frontmatter.value.blog?.inspiring, home?.inspiring]
30
+ .flat()
31
+ .filter((v) => !!v)
32
+ )
33
+ ]
34
+ })
35
+ const inspiringIndex = ref<number>(-1)
36
+ const inspiringTimeout = computed<number>(
37
+ () => frontmatter.value.blog?.inspiringTimeout || home?.inspiringTimeout || 0
26
38
  )
27
- const inspiring = computed({
28
- get() {
29
- return initInspiring.value
30
- },
31
- set(newValue) {
32
- initInspiring.value = newValue
39
+
40
+ watch(inspiringTimeout, () => {
41
+ startTimer()
42
+ })
43
+ const timer = ref<any>(0)
44
+ const startTimer = () => {
45
+ if (timer.value) {
46
+ clearTimeout(timer.value)
47
+ }
48
+ if (inspiringTimeout.value > 0) {
49
+ timer.value = setTimeout(() => {
50
+ changeSlogan()
51
+ }, inspiringTimeout.value)
33
52
  }
53
+ }
54
+ onMounted(() => {
55
+ changeSlogan()
34
56
  })
35
57
 
36
- const homeConfig = useHomeConfig()
58
+ onUnmounted(() => {
59
+ if (timer.value) {
60
+ clearTimeout(timer.value)
61
+ }
62
+ })
37
63
 
38
64
  const changeSlogan = async () => {
39
- if (typeof homeConfig?.handleChangeSlogan !== 'function') {
40
- return
41
- }
42
- const newSlogan = await homeConfig.handleChangeSlogan(inspiring.value)
43
- if (typeof newSlogan !== 'string' || !newSlogan.trim()) {
44
- return
45
- }
65
+ // 顺手启动定时器
66
+ startTimer()
67
+
68
+ if (inspiringList.value.length < 1) return
69
+
70
+ inspiringIndex.value = (inspiringIndex.value + 1) % inspiringList.value.length
71
+ const newValue = inspiringList.value[inspiringIndex.value]
72
+ if (newValue === inspiring.value) return
46
73
 
47
74
  // 重新渲染数据,同时触发动画
48
75
  inspiring.value = ''
49
- setTimeout(async () => {
50
- inspiring.value = newSlogan
51
- })
76
+ setTimeout(() => {
77
+ inspiring.value = newValue
78
+ }, 100)
52
79
  }
53
80
  </script>
54
81
  <style lang="scss" scoped>
@@ -9,7 +9,12 @@
9
9
  <!-- 标题 -->
10
10
  <p class="title" v-if="!inMobile">{{ title }}</p>
11
11
  <!-- 简短描述 -->
12
- <p class="description" v-if="!!description">{{ description }}</p>
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>
13
18
  <!-- 底部补充描述 -->
14
19
  <div class="badge-list" v-if="!inMobile">
15
20
  <span class="split" v-if="author">{{ author }}</span>
@@ -47,15 +52,29 @@ const props = defineProps<{
47
52
  date: string | Date
48
53
  sticky?: number
49
54
  description?: string
55
+ descriptionHTML?: string
50
56
  tag?: string[]
51
57
  author?: string
52
- cover?: string
58
+ cover?: string | boolean
53
59
  pin?: number
54
60
  }>()
55
61
 
56
62
  const showTime = computed(() => {
57
63
  return formatShowDate(props.date)
58
64
  })
65
+
66
+ // function isWrappedWithPreventDefault(element: HTMLElement) {
67
+ // let parent = element.parentElement
68
+
69
+ // while (parent) {
70
+ // if (parent.hasAttribute('preventDefault')) {
71
+ // return true
72
+ // }
73
+ // parent = parent.parentElement
74
+ // }
75
+
76
+ // return false
77
+ // }
59
78
  </script>
60
79
 
61
80
  <style lang="scss" scoped>
@@ -131,6 +150,9 @@ const showTime = computed(() => {
131
150
  -webkit-line-clamp: 2;
132
151
  -webkit-box-orient: vertical;
133
152
  }
153
+ .description-html {
154
+ font-size: 14px;
155
+ }
134
156
  .badge-list {
135
157
  font-size: 13px;
136
158
  color: var(--badge-font-color);
@@ -5,6 +5,7 @@
5
5
  :route="v.route"
6
6
  :title="v.meta.title"
7
7
  :description="v.meta.description"
8
+ :description-h-t-m-l="v.meta.descriptionHTML"
8
9
  :date="v.meta.date"
9
10
  :tag="v.meta.tag"
10
11
  :cover="v.meta.cover"
@@ -42,6 +42,7 @@ export namespace Theme {
42
42
  date: string
43
43
  tag?: string[]
44
44
  description?: string
45
+ descriptionHTML?: string
45
46
  cover?: string
46
47
  hiddenCover?: boolean
47
48
  readingTime?: boolean
@@ -115,7 +116,8 @@ export namespace Theme {
115
116
  export interface HomeBlog {
116
117
  name?: string
117
118
  motto?: string
118
- inspiring?: string
119
+ inspiring?: string | string[]
120
+ inspiringTimeout?: number
119
121
  pageSize?: number
120
122
  }
121
123
 
@@ -268,6 +270,10 @@ export namespace Theme {
268
270
  blog?: BlogConfig
269
271
  }
270
272
  export interface HomeConfig {
273
+ /**
274
+ * @deprecated
275
+ * 此方法已经废弃,这个定义将在未来某一刻被移除,请为 inspiring 配置数租来实现相同的效果
276
+ */
271
277
  handleChangeSlogan?: (oldSlogan: string) => string | Promise<string>
272
278
  }
273
279
  }
package/src/node.ts CHANGED
@@ -6,7 +6,7 @@ import { execSync, spawn, spawnSync } from 'child_process'
6
6
  import path from 'path'
7
7
  import type { SiteConfig, UserConfig } from 'vitepress'
8
8
  import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
9
- import { withMermaid } from 'vitepress-plugin-mermaid'
9
+ import { MermaidMarkdown, MermaidPlugin } from 'vitepress-plugin-mermaid'
10
10
  import { formatDate } from './utils/index'
11
11
  import type { Theme } from './composables/config/index'
12
12
 
@@ -84,9 +84,8 @@ export function getThemeConfig(cfg?: Partial<Theme.BlogConfig>) {
84
84
 
85
85
  // 获取封面图
86
86
  meta.cover =
87
- meta.cover ||
88
- fileContent.match(/[!]\[.*?\]\((https:\/\/.+)\)/)?.[1] ||
89
- ''
87
+ meta.cover ??
88
+ (fileContent.match(/[!]\[.*?\]\((https:\/\/.+)\)/)?.[1] || '')
90
89
 
91
90
  // 是否发布 默认发布
92
91
  if (meta.publish === false) {
@@ -171,25 +170,35 @@ export function getThemeConfig(cfg?: Partial<Theme.BlogConfig>) {
171
170
  ]
172
171
  }
173
172
  }
173
+ const markdownPlugin: any[] = []
174
+ // tabs支持
174
175
  if (cfg?.tabs) {
175
- extraConfig.markdown = {
176
- config(md: any) {
177
- tabsMarkdownPlugin(md)
178
- }
179
- }
176
+ markdownPlugin.push(tabsMarkdownPlugin)
180
177
  }
178
+
179
+ // 流程图支持
181
180
  if (cfg) {
182
181
  cfg.mermaid = cfg?.mermaid ?? false
183
182
  }
184
-
185
- // 流程图支持
186
183
  if (cfg?.mermaid !== false) {
187
- extraConfig.vite = {
188
- ...extraConfig.vite,
189
- resolve: {
190
- alias: {
191
- mermaid: 'mermaid/dist/mermaid.esm.mjs'
192
- }
184
+ markdownPlugin.push(MermaidMarkdown)
185
+ // extraConfig.vite = {
186
+ // ...extraConfig.vite,
187
+ // resolve: {
188
+ // alias: {
189
+ // mermaid: 'mermaid/dist/mermaid.esm.mjs'
190
+ // }
191
+ // }
192
+ // }
193
+ }
194
+
195
+ // 注册markdown插件
196
+ if (markdownPlugin.length) {
197
+ extraConfig.markdown = {
198
+ config(...rest: any[]) {
199
+ markdownPlugin.forEach((plugin) => {
200
+ plugin?.(...rest)
201
+ })
193
202
  }
194
203
  }
195
204
  }
@@ -307,7 +316,37 @@ function getTextSummary(text: string, count = 100) {
307
316
  )
308
317
  }
309
318
 
310
- export function defineConfig(config: UserConfig<Theme.Config>) {
319
+ export function assignMermaid(config: any) {
320
+ if (!config.mermaid) return
321
+
322
+ if (!config.vite) config.vite = {}
323
+ if (!config.vite.plugins) config.vite.plugins = []
324
+ config.vite.plugins.push(MermaidPlugin(config.mermaid))
325
+ if (!config.vite.optimizeDeps) config.vite.optimizeDeps = {}
326
+ config.vite.optimizeDeps = {
327
+ ...config.vite.optimizeDeps,
328
+ include: [
329
+ '@braintree/sanitize-url',
330
+ 'dayjs',
331
+ 'debug',
332
+ 'cytoscape-cose-bilkent',
333
+ 'cytoscape'
334
+ ]
335
+ }
336
+ if (!config.vite.resolve) config.vite.resolve = {}
337
+ if (!config.vite.resolve.alias) config.vite.resolve.alias = {}
338
+
339
+ config.vite.resolve.alias = {
340
+ ...config.vite.resolve.alias,
341
+ 'dayjs/plugin/advancedFormat.js': 'dayjs/esm/plugin/advancedFormat',
342
+ 'dayjs/plugin/customParseFormat.js': 'dayjs/esm/plugin/customParseFormat',
343
+ 'dayjs/plugin/isoWeek.js': 'dayjs/esm/plugin/isoWeek',
344
+ 'cytoscape/dist/cytoscape.umd.js': 'cytoscape/dist/cytoscape.esm.js',
345
+ mermaid: 'mermaid/dist/mermaid.esm.mjs'
346
+ }
347
+ }
348
+
349
+ export function defineConfig(config: UserConfig<Theme.Config>): any {
311
350
  // 兼容低版本主题配置
312
351
  // @ts-ignore
313
352
  if (config.themeConfig?.themeConfig) {
@@ -333,11 +372,12 @@ export function defineConfig(config: UserConfig<Theme.Config>) {
333
372
  const resultConfig =
334
373
  extendThemeConfig.mermaid === false
335
374
  ? config
336
- : withMermaid({
375
+ : {
337
376
  ...config,
338
377
  mermaid:
339
378
  extendThemeConfig.mermaid === true ? {} : extendThemeConfig.mermaid
340
- })
379
+ }
380
+ assignMermaid(resultConfig)
341
381
 
342
382
  // 处理markdown插件
343
383
  if (!resultConfig.markdown) resultConfig.markdown = {}