@sugarat/theme 0.2.30 → 0.3.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.
@@ -52,3 +52,26 @@ export const themeSVG = `<svg width="128" height="128" viewBox="0 0 24 24" xmlns
52
52
  export const icpSVG = '<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" data-v-2f084f89=""><title data-v-2f084f89="">ICP备案号</title><path d="M778.24 163.84c-76.8-40.96-165.888-61.44-269.312-61.44s-192.512 20.48-269.312 61.44h-133.12l23.552 337.92c8.192 113.664 67.584 217.088 162.816 280.576l215.04 144.384 215.04-144.384c96.256-63.488 155.648-166.912 163.84-280.576l23.552-337.92H778.24z m47.104 333.824c-7.168 94.208-56.32 181.248-135.168 233.472l-181.248 120.832L327.68 731.136c-78.848-53.248-129.024-139.264-135.168-233.472L173.056 225.28h136.192v-26.624c58.368-23.552 124.928-34.816 199.68-34.816s141.312 12.288 199.68 34.816V225.28H844.8l-19.456 272.384z" data-v-2f084f89=""></path><path d="M685.056 328.704v-46.08H455.68c2.048-4.096 6.144-9.216 11.264-15.36 5.12-7.168 9.216-12.288 11.264-15.36L419.84 240.64c-31.744 46.08-75.776 87.04-133.12 123.904 4.096 4.096 10.24 11.264 18.432 21.504l17.408 17.408c23.552-15.36 45.056-31.744 63.488-50.176 26.624 25.6 49.152 43.008 67.584 51.2-46.08 15.36-104.448 27.648-175.104 35.84 2.048 5.12 6.144 13.312 9.216 24.576 4.096 11.264 6.144 19.456 7.168 24.576l39.936-7.168v218.112H389.12V680.96h238.592v19.456h54.272V481.28H348.16c60.416-12.288 114.688-27.648 163.84-46.08 49.152 19.456 118.784 34.816 210.944 46.08 5.12-17.408 10.24-34.816 17.408-51.2-62.464-4.096-116.736-12.288-161.792-24.576 38.912-20.48 74.752-46.08 106.496-76.8z m-150.528 194.56h94.208v41.984h-94.208v-41.984z m0 78.848h94.208v41.984h-94.208v-41.984z m-144.384-78.848h94.208v41.984H390.144v-41.984z m0 78.848h94.208v41.984H390.144v-41.984zM424.96 326.656h182.272c-26.624 22.528-57.344 41.984-94.208 57.344-31.744-15.36-61.44-34.816-88.064-57.344z" data-v-2f084f89=""></path></svg>'
53
53
 
54
54
  export const copyrightSVG = '<svg t="1695543755857" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="89399" width="200" height="200"><path d="M512 16C238.066 16 16 238.066 16 512s222.066 496 496 496 496-222.066 496-496S785.934 16 512 16z m234.268 693.506c-3.184 3.734-79.552 91.462-219.702 91.462-169.384 0-288.968-126.52-288.968-291.134 0-162.606 124.008-286.802 287.524-286.802 133.914 0 203.93 74.63 206.844 77.808a24 24 0 0 1 2.476 29.246l-44.76 69.31c-8.098 12.534-25.548 14.702-36.468 4.59-0.466-0.428-53.058-47.76-123.76-47.76-92.232 0-147.832 67.15-147.832 152.164 0 79.204 51.028 159.384 148.554 159.384 77.394 0 130.56-56.676 131.088-57.25 10.264-11.13 28.118-10.066 37.016 2.106l49.094 67.144a24.002 24.002 0 0 1-1.106 29.732z" p-id="89400"></path></svg>'
55
+
56
+ export const aliPaySVG = `
57
+ <svg
58
+ id="mx_n_1711731519286" t="1711731519285" class="icon" viewBox="0 0 1024 1024" version="1.1"
59
+ xmlns="http://www.w3.org/2000/svg" p-id="9945" width="16" height="16"
60
+ >
61
+ <path
62
+ d="M230.404 576.536c-12.087 9.728-25.043 23.93-28.805 41.984-5.12 24.666-1.069 55.541 22.728 79.761 28.828 29.362 72.637 37.398 91.56 38.779 51.4 3.717 106.184-21.772 147.477-50.844 16.184-11.42 43.899-34.349 70.39-69.721-59.37-30.653-133.477-64.557-212.703-61.24-40.47 1.692-69.454 10.084-90.647 21.281z m752.859 135.545C1009.463 650.574 1024 582.968 1024 512 1024 229.688 794.335 0 512 0 229.665 0 0 229.688 0 512c0 282.335 229.665 512 512 512 170.385 0 321.491-83.723 414.631-212.124-87.997-43.742-233.027-115.734-322.36-159.299-42.63 48.596-105.65 97.303-176.84 118.495-44.722 13.29-85.037 18.365-127.199 9.75-41.739-8.548-72.481-28.093-90.401-47.683-9.127-9.995-19.612-22.706-27.203-37.82a71.25 71.25 0 0 0 1.202 3.049s-4.363-7.524-7.702-19.5a85.994 85.994 0 0 1-3.34-18.143 93.517 93.517 0 0 1-0.2-13.045c-0.378-7.702-0.066-15.783 1.67-24.064 4.185-20.235 12.822-43.81 35.172-65.692 49.063-48.039 114.777-50.621 148.814-50.42 50.421 0.289 138.04 22.35 211.812 48.439 20.436-43.52 33.547-90.068 42.007-121.1H305.308v-33.168h157.518v-66.337H272.139v-33.169h190.687v-66.315c0-9.105 1.803-16.584 16.584-16.584h74.619v82.899h207.293v33.169H554.029v66.337h165.82s-16.65 92.828-68.719 184.32c115.557 41.272 278.128 104.849 332.133 126.086z"
63
+ fill="white" p-id="9946"
64
+ />
65
+ </svg>
66
+ `
67
+ export const weChatPaySVG = `
68
+ <svg
69
+ t="1711730357270" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
70
+ p-id="4392" width="16" height="16"
71
+ >
72
+ <path
73
+ d="M512 1024a512 512 0 1 1 512-512 512 512 0 0 1-512 512z m-112.523636-836.538182c-144.989091 0-262.516364 100.538182-262.516364 224.465455 0 74.007273 42.123636 139.636364 106.705455 180.363636l-19.549091 78.312727 86.807272-47.592727a301.265455 301.265455 0 0 0 88.669091 13.381818h2.210909a178.967273 178.967273 0 0 1-3.607272-34.909091c0-115.083636 109.498182-208.407273 244.363636-208.407272 6.167273 0 11.636364 0 18.152727 0.814545-10.589091-115.665455-123.461818-206.778182-261.469091-206.778182z m246.690909 226.443637c-124.741818 0-225.861818 86.109091-225.861818 192.465454s101.003636 192.349091 225.861818 192.349091a257.047273 257.047273 0 0 0 99.723636-20.014545l77.265455 40.610909L802.909091 744.727273a179.316364 179.316364 0 0 0 69.003636-138.24c0-106.24-101.12-192.465455-225.861818-192.465455z m81.454545 152.087272a31.767273 31.767273 0 1 1 32.349091-31.767272 32 32 0 0 1-32.349091 31.767272z m-164.072727 0a31.767273 31.767273 0 1 1 32.349091-31.767272 32 32 0 0 1-32.349091 31.767272zM502.341818 373.527273a34.909091 34.909091 0 1 1 34.909091-34.909091 34.909091 34.909091 0 0 1-34.909091 34.909091z m-206.196363 0a34.909091 34.909091 0 1 1 34.90909-34.909091 34.909091 34.909091 0 0 1-34.90909 34.909091z m0 0"
74
+ fill="white" p-id="4393"
75
+ />
76
+ </svg>
77
+ `
@@ -0,0 +1,46 @@
1
+ import { useData } from 'vitepress'
2
+ import { nextTick, provide } from 'vue'
3
+ import { useDarkTransitionConfig } from '../composables/config/blog'
4
+
5
+ export function useDarkTransition() {
6
+ const { isDark } = useData()
7
+
8
+ const isOpenDarkTransition = useDarkTransitionConfig()
9
+
10
+ if (!isOpenDarkTransition) {
11
+ return
12
+ }
13
+ const enableTransitions = () =>
14
+ 'startViewTransition' in document
15
+ && window.matchMedia('(prefers-reduced-motion: no-preference)').matches
16
+
17
+ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
18
+ if (!enableTransitions()) {
19
+ isDark.value = !isDark.value
20
+ return
21
+ }
22
+
23
+ const clipPath = [
24
+ `circle(0px at ${x}px ${y}px)`,
25
+ `circle(${Math.hypot(
26
+ Math.max(x, innerWidth - x),
27
+ Math.max(y, innerHeight - y)
28
+ )}px at ${x}px ${y}px)`
29
+ ]
30
+
31
+ // @ts-expect-error
32
+ await document.startViewTransition(async () => {
33
+ isDark.value = !isDark.value
34
+ await nextTick()
35
+ }).ready
36
+
37
+ document.documentElement.animate(
38
+ { clipPath: isDark.value ? clipPath.reverse() : clipPath },
39
+ {
40
+ duration: 300,
41
+ easing: 'ease-in',
42
+ pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`
43
+ }
44
+ )
45
+ })
46
+ }
@@ -59,15 +59,21 @@ export function useOml2d() {
59
59
  ...defaultOptions.tips,
60
60
  ...oml2dOptions.tips,
61
61
  style: {
62
+ // @ts-expect-error
62
63
  ...defaultOptions?.tips?.style,
64
+ // @ts-expect-error
63
65
  ...oml2dOptions?.tips?.style
64
66
  },
65
67
  mobileStyle: {
68
+ // @ts-expect-error
66
69
  ...defaultOptions?.tips?.mobileStyle,
70
+ // @ts-expect-error
67
71
  ...oml2dOptions?.tips?.mobileStyle
68
72
  },
69
73
  copyTips: {
74
+ // @ts-expect-error
70
75
  ...defaultOptions?.tips?.copyTips,
76
+ // @ts-expect-error
71
77
  ...oml2dOptions?.tips?.copyTips
72
78
  }
73
79
  }
package/src/node.ts CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  patchOptimizeDeps,
7
7
  registerMdPlugins,
8
8
  } from './utils/node/mdPlugins'
9
- import { checkConfig, getArticles, patchVPThemeConfig } from './utils/node/theme'
9
+ import { checkConfig, getArticles, patchVPConfig, patchVPThemeConfig } from './utils/node/theme'
10
10
  import { getVitePlugins, registerVitePlugins } from './utils/node/vitePlugins'
11
11
 
12
12
  /**
@@ -34,6 +34,8 @@ export function getThemeConfig(cfg?: Partial<Theme.BlogConfig>) {
34
34
  // patch extraVPConfig
35
35
  patchMermaidPluginCfg(extraVPConfig)
36
36
  patchOptimizeDeps(extraVPConfig)
37
+
38
+ patchVPConfig(extraVPConfig, cfg)
37
39
  return {
38
40
  themeConfig: {
39
41
  blog: {
@@ -0,0 +1,23 @@
1
+ ::view-transition-old(root),
2
+ ::view-transition-new(root) {
3
+ animation: none;
4
+ mix-blend-mode: normal;
5
+ }
6
+
7
+ ::view-transition-old(root),
8
+ .dark::view-transition-new(root) {
9
+ z-index: 1;
10
+ }
11
+
12
+ ::view-transition-new(root),
13
+ .dark::view-transition-old(root) {
14
+ z-index: 9999;
15
+ }
16
+
17
+ .blog-theme-layout .VPSwitchAppearance {
18
+ width: 22px !important;
19
+ }
20
+
21
+ .blog-theme-layout .VPSwitchAppearance .check {
22
+ transform: none !important;
23
+ }
@@ -0,0 +1,59 @@
1
+ import type { PluginOption } from 'vite'
2
+ import type { SiteConfig } from 'vitepress'
3
+ import type { Theme } from '../../composables/config/index'
4
+ import { getArticleMeta } from './theme'
5
+ import { debounce, isEqual } from './index'
6
+
7
+ export function themeReloadPlugin() {
8
+ let blogConfig: Theme.BlogConfig
9
+ let vitepressConfig: SiteConfig
10
+ let docsDir: string
11
+
12
+ const generateRoute = (filepath: string) => {
13
+ return filepath.replace(docsDir, '').replace('.md', '')
14
+ }
15
+
16
+ return {
17
+ name: '@sugarat/theme-reload',
18
+ apply: 'serve',
19
+ configureServer(server) {
20
+ const restart = debounce(() => {
21
+ server.restart()
22
+ }, 500)
23
+ server.watcher.on('add', (path) => {
24
+ const route = generateRoute(path)
25
+ const meta = getArticleMeta(path, route, blogConfig?.timeZone)
26
+ blogConfig.pagesData.push({
27
+ route,
28
+ meta
29
+ })
30
+ restart()
31
+ })
32
+
33
+ server.watcher.on('change', (path: string) => {
34
+ const route = generateRoute(path)
35
+ const meta = getArticleMeta(path, route, blogConfig?.timeZone)
36
+ const matched = blogConfig.pagesData.find(v => v.route === route)
37
+
38
+ if (matched && !isEqual(matched.meta, meta, ['date', 'description'])) {
39
+ matched.meta = meta
40
+ restart()
41
+ }
42
+ })
43
+
44
+ server.watcher.on('unlink', (path) => {
45
+ const route = generateRoute(path)
46
+ const idx = blogConfig.pagesData.findIndex(v => v.route === route)
47
+ if (idx >= 0) {
48
+ blogConfig.pagesData.splice(idx, 1)
49
+ restart()
50
+ }
51
+ })
52
+ },
53
+ configResolved(config: any) {
54
+ vitepressConfig = config.vitepress
55
+ docsDir = vitepressConfig.srcDir
56
+ blogConfig = config.vitepress.site.themeConfig.blog
57
+ },
58
+ } as PluginOption
59
+ }
@@ -2,7 +2,6 @@
2
2
  /* eslint-disable prefer-rest-params */
3
3
  import { spawn, spawnSync } from 'node:child_process'
4
4
  import path from 'node:path'
5
- import { formatDate } from '../client'
6
5
 
7
6
  export function clearMatterContent(content: string) {
8
7
  let first___: unknown
@@ -31,16 +30,10 @@ export function clearMatterContent(content: string) {
31
30
  .join('\n')
32
31
  )
33
32
  }
33
+
34
34
  export function getDefaultTitle(content: string) {
35
- const title
36
- = clearMatterContent(content)
37
- .split('\n')
38
- ?.find((str) => {
39
- return str.startsWith('# ')
40
- })
41
- ?.slice(2)
42
- .replace(/^\s+|\s+$/g, '') || ''
43
- return title
35
+ const match = content.match(/^(#+)\s+(.+)/m)
36
+ return match?.[2] || ''
44
37
  }
45
38
 
46
39
  export function getFileBirthTime(url: string) {
@@ -57,10 +50,10 @@ export function getFileBirthTime(url: string) {
57
50
  }
58
51
  }
59
52
  catch (error) {
60
- return formatDate(date)
53
+ return date
61
54
  }
62
55
 
63
- return formatDate(date)
56
+ return date
64
57
  }
65
58
 
66
59
  export function getGitTimestamp(file: string) {
@@ -79,8 +72,9 @@ export function getGitTimestamp(file: string) {
79
72
 
80
73
  export function getTextSummary(text: string, count = 100) {
81
74
  return (
82
- clearMatterContent(text)
83
- .match(/^# ([\s\S]+)/m)?.[1]
75
+ text
76
+ // 首个标题
77
+ ?.replace(/^#+\s+.*/, '')
84
78
  // 除去标题
85
79
  ?.replace(/#/g, '')
86
80
  // 除去图片
@@ -91,9 +85,9 @@ export function getTextSummary(text: string, count = 100) {
91
85
  ?.replace(/\*\*(.*?)\*\*/g, '$1')
92
86
  ?.split('\n')
93
87
  ?.filter(v => !!v)
94
- ?.slice(1)
95
88
  ?.join('\n')
96
89
  ?.replace(/>(.*)/, '')
90
+ ?.trim()
97
91
  ?.slice(0, count)
98
92
  )
99
93
  }
@@ -151,3 +145,43 @@ export function getFirstImagURLFromMD(content: string, route: string) {
151
145
 
152
146
  return joinPath('/', relativePath)
153
147
  }
148
+
149
+ export function debounce(func: any, delay = 1000) {
150
+ let timeoutId: any
151
+ return (...rest: any[]) => {
152
+ clearTimeout(timeoutId)
153
+ timeoutId = setTimeout(() => {
154
+ func(...rest)
155
+ }, delay)
156
+ }
157
+ }
158
+
159
+ export function isEqual(obj1: any, obj2: any, excludeKeys: string[] = []) {
160
+ const keys1 = Object.keys(obj1).filter(key => !excludeKeys.includes(key))
161
+ const keys2 = Object.keys(obj2).filter(key => !excludeKeys.includes(key))
162
+
163
+ if (keys1.length !== keys2.length) {
164
+ return false
165
+ }
166
+
167
+ for (const key of keys1) {
168
+ if (!keys2.includes(key)) {
169
+ return false
170
+ }
171
+ const val1 = obj1[key]
172
+ const val2 = obj2[key]
173
+ const areObjects = isObject(val1) && isObject(val2)
174
+ if (
175
+ (areObjects && !isEqual(val1, val2, excludeKeys))
176
+ || (!areObjects && val1 !== val2)
177
+ ) {
178
+ return false
179
+ }
180
+ }
181
+
182
+ return true
183
+ }
184
+
185
+ export function isObject(obj: any) {
186
+ return obj != null && typeof obj === 'object'
187
+ }
@@ -21,111 +21,114 @@ export function patchDefaultThemeSideBar(cfg?: Partial<Theme.BlogConfig>) {
21
21
  : undefined
22
22
  }
23
23
 
24
- // hack:RSS用
25
- export const pageMap = new Map<string, string>()
24
+ export function getPageRoute(filepath: string, srcDir: string) {
25
+ let route = filepath.replace('.md', '')
26
+ // 去除 srcDir 处理目录名
27
+ // TODO:优化 路径处理,同VitePress 内部一致
28
+ if (route.startsWith('./')) {
29
+ route = route.replace(
30
+ new RegExp(
31
+ `^\\.\\/${path
32
+ .join(srcDir, '/')
33
+ .replace(new RegExp(`\\${path.sep}`, 'g'), '/')}`
34
+ ),
35
+ ''
36
+ )
37
+ }
38
+ else {
39
+ route = route.replace(
40
+ new RegExp(
41
+ `^${path
42
+ .join(srcDir, '/')
43
+ .replace(new RegExp(`\\${path.sep}`, 'g'), '/')}`
44
+ ),
45
+ ''
46
+ )
47
+ }
48
+ return `/${route}`
49
+ }
26
50
 
51
+ const defaultTimeZoneOffset = new Date().getTimezoneOffset() / -60
52
+ export function getArticleMeta(filepath: string, route: string, timeZone = defaultTimeZoneOffset) {
53
+ const fileContent = fs.readFileSync(filepath, 'utf-8')
54
+
55
+ const { data: frontmatter, excerpt, content } = matter(fileContent, {
56
+ excerpt: true,
57
+ })
58
+
59
+ const meta: Partial<Theme.PageMeta> = {
60
+ ...frontmatter
61
+ }
62
+
63
+ if (!meta.title) {
64
+ meta.title = getDefaultTitle(content)
65
+ }
66
+ if (!meta.date) {
67
+ meta.date = formatDate(getFileBirthTime(filepath))
68
+ }
69
+ else {
70
+ meta.date = formatDate(
71
+ new Date(`${new Date(meta.date).toUTCString()}+${timeZone}`)
72
+ )
73
+ }
74
+
75
+ // 处理tags和categories,兼容历史文章
76
+ meta.categories
77
+ = typeof meta.categories === 'string'
78
+ ? [meta.categories]
79
+ : meta.categories
80
+ meta.tags = typeof meta.tags === 'string' ? [meta.tags] : meta.tags
81
+ meta.tag = [meta.tag || []]
82
+ .flat()
83
+ .concat([
84
+ ...new Set([...(meta.categories || []), ...(meta.tags || [])])
85
+ ])
86
+
87
+ // 获取摘要信息
88
+ // TODO:摘要生成优化
89
+ meta.description
90
+ = meta.description || getTextSummary(content, 100) || excerpt
91
+
92
+ // 获取封面图
93
+ meta.cover
94
+ = meta.cover
95
+ ?? (getFirstImagURLFromMD(fileContent, route))
96
+
97
+ // 是否发布 默认发布
98
+ if (meta.publish === false) {
99
+ meta.hidden = true
100
+ meta.recommend = false
101
+ }
102
+ return meta as Theme.PageMeta
103
+ }
27
104
  export function getArticles(cfg?: Partial<Theme.BlogConfig>) {
28
105
  const srcDir = cfg?.srcDir || process.argv.slice(2)?.[1] || '.'
29
106
  const files = glob.sync(`${srcDir}/**/*.md`, { ignore: ['node_modules'] })
30
107
 
31
108
  // 文章数据
32
- const data = files
33
- .map((v) => {
34
- let route = v
35
- // 处理文件后缀名
36
- .replace('.md', '')
37
-
38
- // 去除 srcDir 处理目录名
39
- if (route.startsWith('./')) {
40
- route = route.replace(
41
- new RegExp(
42
- `^\\.\\/${path
43
- .join(srcDir, '/')
44
- .replace(new RegExp(`\\${path.sep}`, 'g'), '/')}`
45
- ),
46
- ''
47
- )
48
- }
49
- else {
50
- route = route.replace(
51
- new RegExp(
52
- `^${path
53
- .join(srcDir, '/')
54
- .replace(new RegExp(`\\${path.sep}`, 'g'), '/')}`
55
- ),
56
- ''
57
- )
58
- }
59
- // hack:RSS使用
60
- pageMap.set(`/${route}`, v)
61
-
62
- const fileContent = fs.readFileSync(v, 'utf-8')
63
- // TODO:摘要生成优化
64
- // TODO: 用上内容content
65
- const { data: frontmatter, excerpt } = matter(fileContent, {
66
- excerpt: true
67
- })
68
-
69
- const meta: Partial<Theme.PageMeta> = {
70
- ...frontmatter
71
- }
72
-
73
- if (!meta.title) {
74
- // TODO:优化标题的采集
75
- meta.title = getDefaultTitle(fileContent)
76
- }
77
- if (!meta.date) {
78
- // getGitTimestamp(v).then((v) => {
79
- // meta.date = formatDate(v)
80
- // })
81
- meta.date = getFileBirthTime(v)
82
- }
83
- else {
84
- const timeZone = cfg?.timeZone ?? 8
85
- meta.date = formatDate(
86
- new Date(`${new Date(meta.date).toUTCString()}+${timeZone}`)
87
- )
88
- }
89
-
90
- // 处理tags和categories,兼容历史文章
91
- meta.categories
92
- = typeof meta.categories === 'string'
93
- ? [meta.categories]
94
- : meta.categories
95
- meta.tags = typeof meta.tags === 'string' ? [meta.tags] : meta.tags
96
- meta.tag = [meta.tag || []]
97
- .flat()
98
- .concat([
99
- ...new Set([...(meta.categories || []), ...(meta.tags || [])])
100
- ])
101
-
102
- // 获取摘要信息
103
- const wordCount = 100
104
- meta.description
105
- = meta.description || getTextSummary(fileContent, wordCount)
106
-
107
- // 获取封面图
108
- meta.cover
109
- = meta.cover
110
- ?? (getFirstImagURLFromMD(fileContent, `/${route}`))
111
-
112
- // 是否发布 默认发布
113
- if (meta.publish === false) {
114
- meta.hidden = true
115
- meta.recommend = false
116
- }
117
-
109
+ const pageData = files
110
+ .map((filepath) => {
111
+ const route = getPageRoute(filepath, srcDir)
112
+ const meta = getArticleMeta(filepath, route, cfg?.timeZone)
118
113
  return {
119
- route: `/${route}`,
114
+ route,
120
115
  meta
121
116
  }
122
117
  })
123
118
  .filter(v => v.meta.layout !== 'home')
124
- return data as Theme.PageData[]
119
+ return pageData as Theme.PageData[]
125
120
  }
126
121
 
127
122
  export function patchVPConfig(vpConfig: any, cfg?: Partial<Theme.BlogConfig>) {
128
- // TODO: 待确定场景
123
+ vpConfig.head = vpConfig.head || []
124
+ // Artalk 资源地址
125
+ if (cfg?.comment && 'type' in cfg.comment && cfg?.comment?.type === 'artalk') {
126
+ const server = cfg.comment?.options?.server
127
+ if (server) {
128
+ vpConfig.head.push(['link', { href: `${server}/dist/Artalk.css`, rel: 'stylesheet' }])
129
+ vpConfig.head.push(['script', { src: `${server}/dist/Artalk.js`, id: 'artalk-script' }])
130
+ }
131
+ }
129
132
  }
130
133
 
131
134
  export function patchVPThemeConfig(
@@ -12,6 +12,7 @@ import {
12
12
  import { RssPlugin } from 'vitepress-plugin-rss'
13
13
  import type { Theme } from '../../composables/config/index'
14
14
  import { _require } from './mdPlugins'
15
+ import { themeReloadPlugin } from './hot-reload-plugin'
15
16
  import { joinPath } from './index'
16
17
 
17
18
  export function getVitePlugins(cfg?: Partial<Theme.BlogConfig>) {
@@ -19,10 +20,16 @@ export function getVitePlugins(cfg?: Partial<Theme.BlogConfig>) {
19
20
 
20
21
  // Build完后运行的一系列列方法
21
22
  const buildEndFn: any[] = []
23
+
22
24
  // 执行自定义的 buildEnd 钩子
23
25
  plugins.push(inlineBuildEndPlugin(buildEndFn))
26
+
24
27
  // 处理cover image的路径(暂只支持自动识别的文章首图)
25
28
  plugins.push(coverImgTransform())
29
+
30
+ // 自动重载首页
31
+ plugins.push(themeReloadPlugin())
32
+
26
33
  // 内置简化版的pagefind
27
34
  if (cfg && cfg.search !== false) {
28
35
  const ops = cfg.search instanceof Object ? cfg.search : {}
@@ -47,13 +54,6 @@ export function getVitePlugins(cfg?: Partial<Theme.BlogConfig>) {
47
54
  if (cfg?.RSS) {
48
55
  plugins.push(RssPlugin(cfg.RSS))
49
56
  }
50
- // 未来移除使用
51
- // if (cfg && cfg.search !== undefined) {
52
- // console.log(
53
- // '已从内部移除 pagefind 支持,请单独安装 vitepress-plugin-pagefind 插件使用'
54
- // )
55
- // }
56
-
57
57
  return plugins
58
58
  }
59
59
 
@@ -1,3 +1,13 @@
1
+ import type Artalk, { ArtalkConfig } from 'artalk'
2
+
3
+ declare global {
4
+ interface Window {
5
+ Artalk: {
6
+ init(options: Partial<ArtalkConfig>): Artalk
7
+ }
8
+ }
9
+ }
10
+
1
11
  declare module '*.vue' {
2
12
  import type { ComponentOptions } from 'vue'
3
13