@sugarat/theme 0.1.48 → 0.1.50

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
@@ -260,7 +260,7 @@ declare namespace Theme {
260
260
  /**
261
261
  * 设置解析 frontmatter 里 date 的时区
262
262
  * @default 8 => 'UTC+8'
263
- * */
263
+ */
264
264
  timeZone?: number;
265
265
  /**
266
266
  * 启用RSS配置
@@ -299,6 +299,7 @@ declare namespace Theme {
299
299
  * @description (0 不限制;> 1 会按照日期排序对输出内容进行调整)
300
300
  */
301
301
  limit?: number;
302
+ ariaLabel?: string;
302
303
  };
303
304
  interface Config extends DefaultTheme.Config {
304
305
  blog?: BlogConfig;
package/node.js CHANGED
@@ -197,7 +197,7 @@ var tabsPlugin = (md) => {
197
197
  };
198
198
 
199
199
  // src/utils/node/index.ts
200
- var import_child_process = require("child_process");
200
+ var import_node_child_process = require("child_process");
201
201
 
202
202
  // src/utils/client/index.ts
203
203
  function formatDate(d, fmt = "yyyy-MM-dd hh:mm:ss") {
@@ -211,7 +211,7 @@ function formatDate(d, fmt = "yyyy-MM-dd hh:mm:ss") {
211
211
  "m+": d.getMinutes(),
212
212
  "s+": d.getSeconds(),
213
213
  "q+": Math.floor((d.getMonth() + 3) / 3),
214
- S: d.getMilliseconds()
214
+ "S": d.getMilliseconds()
215
215
  };
216
216
  if (/(y+)/.test(fmt)) {
217
217
  fmt = fmt.replace(
@@ -258,7 +258,7 @@ function getDefaultTitle(content) {
258
258
  function getFileBirthTime(url) {
259
259
  let date = new Date();
260
260
  try {
261
- const infoStr = (0, import_child_process.spawnSync)("git", ["log", "-1", '--pretty="%ci"', url]).stdout?.toString().replace(/["']/g, "").trim();
261
+ const infoStr = (0, import_node_child_process.spawnSync)("git", ["log", "-1", '--pretty="%ci"', url]).stdout?.toString().replace(/["']/g, "").trim();
262
262
  if (infoStr) {
263
263
  date = new Date(infoStr);
264
264
  }
@@ -277,11 +277,11 @@ function aliasObjectToArray(obj) {
277
277
  }));
278
278
  }
279
279
  var EXTERNAL_URL_RE = /^[a-z]+:/i;
280
- function joinPath(base, path3) {
281
- return `${base}${path3}`.replace(/\/+/g, "/");
280
+ function joinPath(base, path4) {
281
+ return `${base}${path4}`.replace(/\/+/g, "/");
282
282
  }
283
- function withBase(base, path3) {
284
- return EXTERNAL_URL_RE.test(path3) || path3.startsWith(".") ? path3 : joinPath(base, path3);
283
+ function withBase(base, path4) {
284
+ return EXTERNAL_URL_RE.test(path4) || path4.startsWith(".") ? path4 : joinPath(base, path4);
285
285
  }
286
286
 
287
287
  // src/utils/node/mdPlugins.ts
@@ -327,7 +327,7 @@ function assignMermaid(config) {
327
327
  ...aliasObjectToArray({
328
328
  ...config.vite.resolve.alias,
329
329
  "cytoscape/dist/cytoscape.umd.js": "cytoscape/dist/cytoscape.esm.js",
330
- mermaid: "mermaid/dist/mermaid.esm.mjs"
330
+ "mermaid": "mermaid/dist/mermaid.esm.mjs"
331
331
  }),
332
332
  { find: /^dayjs\/(.*).js/, replacement: "dayjs/esm/$1" }
333
333
  ];
@@ -360,10 +360,11 @@ function supportRunExtendsPlugin(config) {
360
360
  }
361
361
 
362
362
  // src/utils/node/theme.ts
363
+ var import_node_fs = __toESM(require("fs"));
364
+ var import_node_path = __toESM(require("path"));
365
+ var import_node_process = __toESM(require("process"));
363
366
  var import_fast_glob = __toESM(require("fast-glob"));
364
367
  var import_gray_matter = __toESM(require("gray-matter"));
365
- var import_fs = __toESM(require("fs"));
366
- var import_path = __toESM(require("path"));
367
368
  function patchDefaultThemeSideBar(cfg) {
368
369
  return cfg?.blog !== false && cfg?.recommend !== false ? {
369
370
  sidebar: [
@@ -376,27 +377,27 @@ function patchDefaultThemeSideBar(cfg) {
376
377
  }
377
378
  var pageMap = /* @__PURE__ */ new Map();
378
379
  function getArticles(cfg) {
379
- const srcDir = cfg?.srcDir || process.argv.slice(2)?.[1] || ".";
380
+ const srcDir = cfg?.srcDir || import_node_process.default.argv.slice(2)?.[1] || ".";
380
381
  const files = import_fast_glob.default.sync(`${srcDir}/**/*.md`, { ignore: ["node_modules"] });
381
382
  const data = files.map((v) => {
382
383
  let route = v.replace(".md", "");
383
384
  if (route.startsWith("./")) {
384
385
  route = route.replace(
385
386
  new RegExp(
386
- `^\\.\\/${import_path.default.join(srcDir, "/").replace(new RegExp(`\\${import_path.default.sep}`, "g"), "/")}`
387
+ `^\\.\\/${import_node_path.default.join(srcDir, "/").replace(new RegExp(`\\${import_node_path.default.sep}`, "g"), "/")}`
387
388
  ),
388
389
  ""
389
390
  );
390
391
  } else {
391
392
  route = route.replace(
392
393
  new RegExp(
393
- `^${import_path.default.join(srcDir, "/").replace(new RegExp(`\\${import_path.default.sep}`, "g"), "/")}`
394
+ `^${import_node_path.default.join(srcDir, "/").replace(new RegExp(`\\${import_node_path.default.sep}`, "g"), "/")}`
394
395
  ),
395
396
  ""
396
397
  );
397
398
  }
398
399
  pageMap.set(`/${route}`, v);
399
- const fileContent = import_fs.default.readFileSync(v, "utf-8");
400
+ const fileContent = import_node_fs.default.readFileSync(v, "utf-8");
400
401
  const { data: frontmatter, excerpt } = (0, import_gray_matter.default)(fileContent, {
401
402
  excerpt: true
402
403
  });
@@ -433,15 +434,17 @@ function getArticles(cfg) {
433
434
  }).filter((v) => v.meta.layout !== "home");
434
435
  return data;
435
436
  }
437
+ var svgIcon = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 448 512"><title>RSS</title><path d="M400 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM112 416c-26.51 0-48-21.49-48-48s21.49-48 48-48s48 21.49 48 48s-21.49 48-48 48zm157.533 0h-34.335c-6.011 0-11.051-4.636-11.442-10.634c-5.214-80.05-69.243-143.92-149.123-149.123c-5.997-.39-10.633-5.431-10.633-11.441v-34.335c0-6.535 5.468-11.777 11.994-11.425c110.546 5.974 198.997 94.536 204.964 204.964c.352 6.526-4.89 11.994-11.425 11.994zm103.027 0h-34.334c-6.161 0-11.175-4.882-11.427-11.038c-5.598-136.535-115.204-246.161-251.76-251.76C68.882 152.949 64 147.935 64 141.774V107.44c0-6.454 5.338-11.664 11.787-11.432c167.83 6.025 302.21 141.191 308.205 308.205c.232 6.449-4.978 11.787-11.432 11.787z" fill="currentColor"></path></svg>';
436
438
  function patchVPThemeConfig(cfg, vpThemeConfig = {}) {
437
439
  const RSS = cfg?.RSS;
438
440
  if (RSS && RSS.icon !== false) {
439
441
  vpThemeConfig.socialLinks = [
440
442
  {
441
443
  icon: {
442
- svg: '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 448 512"><path d="M400 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM112 416c-26.51 0-48-21.49-48-48s21.49-48 48-48s48 21.49 48 48s-21.49 48-48 48zm157.533 0h-34.335c-6.011 0-11.051-4.636-11.442-10.634c-5.214-80.05-69.243-143.92-149.123-149.123c-5.997-.39-10.633-5.431-10.633-11.441v-34.335c0-6.535 5.468-11.777 11.994-11.425c110.546 5.974 198.997 94.536 204.964 204.964c.352 6.526-4.89 11.994-11.425 11.994zm103.027 0h-34.334c-6.161 0-11.175-4.882-11.427-11.038c-5.598-136.535-115.204-246.161-251.76-251.76C68.882 152.949 64 147.935 64 141.774V107.44c0-6.454 5.338-11.664 11.787-11.432c167.83 6.025 302.21 141.191 308.205 308.205c.232 6.449-4.978 11.787-11.432 11.787z" fill="currentColor"></path></svg>'
444
+ svg: svgIcon
443
445
  },
444
- link: RSS?.url
446
+ link: RSS?.url,
447
+ ariaLabel: RSS?.ariaLabel || "RSS"
445
448
  }
446
449
  ];
447
450
  }
@@ -450,11 +453,14 @@ function patchVPThemeConfig(cfg, vpThemeConfig = {}) {
450
453
  }
451
454
 
452
455
  // src/utils/node/vitePlugins.ts
456
+ var import_node_path3 = __toESM(require("path"));
457
+ var import_node_child_process2 = require("child_process");
458
+ var import_node_process2 = __toESM(require("process"));
453
459
  var import_vitepress_plugin_pagefind = require("vitepress-plugin-pagefind");
454
460
 
455
461
  // src/utils/node/genFeed.ts
456
- var import_path2 = __toESM(require("path"));
457
- var import_fs2 = __toESM(require("fs"));
462
+ var import_node_path2 = __toESM(require("path"));
463
+ var import_node_fs2 = __toESM(require("fs"));
458
464
  var import_feed = require("feed");
459
465
  async function genFeed(config) {
460
466
  const blogCfg = config.userConfig.themeConfig.blog;
@@ -497,7 +503,7 @@ async function genFeed(config) {
497
503
  let html;
498
504
  const filepath = pageMap.get(route);
499
505
  if (filepath) {
500
- const fileContent = import_fs2.default.readFileSync(filepath, "utf-8");
506
+ const fileContent = import_node_fs2.default.readFileSync(filepath, "utf-8");
501
507
  html = mdRender.render(fileContent);
502
508
  }
503
509
  feed.addItem({
@@ -516,8 +522,8 @@ async function genFeed(config) {
516
522
  });
517
523
  }
518
524
  const RSSFilename = filename || "feed.rss";
519
- const RSSFile = import_path2.default.join(config.outDir, RSSFilename);
520
- (0, import_fs2.writeFileSync)(RSSFile, feed.rss2());
525
+ const RSSFile = import_node_path2.default.join(config.outDir, RSSFilename);
526
+ (0, import_node_fs2.writeFileSync)(RSSFile, feed.rss2());
521
527
  console.log("\u{1F389} RSS generated", RSSFilename);
522
528
  console.log("rss filepath:", RSSFile);
523
529
  console.log("rss url:", `${baseUrl}${config.site.base + RSSFilename}`);
package/package.json CHANGED
@@ -1,8 +1,22 @@
1
1
  {
2
2
  "name": "@sugarat/theme",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
5
- "main": "src/index.ts",
5
+ "author": "sugar",
6
+ "license": "MIT",
7
+ "homepage": "https://theme.sugarat.top",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/ATQQ/sugar-blog.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/ATQQ/sugar-blog/issues"
14
+ },
15
+ "keywords": [
16
+ "vitepress",
17
+ "theme",
18
+ "粥里有勺糖"
19
+ ],
6
20
  "exports": {
7
21
  "./node": {
8
22
  "types": "./node.d.ts",
@@ -11,27 +25,13 @@
11
25
  "./package.json": "./package.json",
12
26
  ".": "./src/index.ts"
13
27
  },
28
+ "main": "src/index.ts",
14
29
  "files": [
15
- "src",
16
- "types",
30
+ "node.d.ts",
17
31
  "node.js",
18
- "node.d.ts"
19
- ],
20
- "repository": {
21
- "type": "git",
22
- "url": "git+https://github.com/ATQQ/sugar-blog.git"
23
- },
24
- "keywords": [
25
- "vitepress",
26
- "theme",
27
- "粥里有勺糖"
32
+ "src",
33
+ "types"
28
34
  ],
29
- "author": "sugar",
30
- "license": "MIT",
31
- "homepage": "https://theme.sugarat.top",
32
- "bugs": {
33
- "url": "https://github.com/ATQQ/sugar-blog/issues"
34
- },
35
35
  "dependencies": {
36
36
  "@mdit-vue/shared": "^0.12.0",
37
37
  "@mermaid-js/mermaid-mindmap": "^9.3.0",
@@ -43,19 +43,19 @@
43
43
  "highlight.js": "^11.7.0",
44
44
  "mermaid": "^10.2.4",
45
45
  "vitepress-plugin-mermaid": "^2.0.13",
46
- "vitepress-plugin-pagefind": "0.2.9",
46
+ "vitepress-plugin-pagefind": "0.2.10",
47
47
  "vue-command-palette": "^0.1.4"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@element-plus/icons-vue": "^2.1.0",
51
51
  "element-plus": "^2.3.4",
52
+ "pagefind": "1.0.3",
52
53
  "sass": "^1.56.1",
53
54
  "tsup": " ^6.5.0",
54
55
  "typescript": "^4.8.2",
55
56
  "vitepress": "1.0.0-rc.14",
56
57
  "vitepress-plugin-tabs": "^0.2.0",
57
- "vue": "^3.3.4",
58
- "pagefind": "1.0.3"
58
+ "vue": "^3.3.4"
59
59
  },
60
60
  "scripts": {
61
61
  "dev": "npm run build:node && npm run dev:docs",
@@ -1,22 +1,6 @@
1
- <template>
2
- <div class="global-alert" v-if="show" data-pagefind-ignore="all">
3
- <el-alert
4
- :title="alertProps?.title"
5
- :type="alertProps?.type"
6
- :show-icon="alertProps?.showIcon"
7
- :center="alertProps?.center"
8
- :closable="alertProps?.closable"
9
- :close-text="alertProps?.closeText"
10
- :description="alertProps?.description"
11
- >
12
- <div v-if="alertProps?.html" v-html="alertProps?.html"></div>
13
- </el-alert>
14
- </div>
15
- </template>
16
-
17
1
  <script lang="ts" setup>
18
2
  import { ElAlert } from 'element-plus'
19
- import { ref, onMounted } from 'vue'
3
+ import { onMounted, ref } from 'vue'
20
4
  import { useBlogConfig } from '../composables/config/blog'
21
5
 
22
6
  const { alert: alertProps } = useBlogConfig()
@@ -46,6 +30,22 @@ onMounted(() => {
46
30
  })
47
31
  </script>
48
32
 
33
+ <template>
34
+ <div v-if="show" class="global-alert" data-pagefind-ignore="all">
35
+ <ElAlert
36
+ :title="alertProps?.title"
37
+ :type="alertProps?.type"
38
+ :show-icon="alertProps?.showIcon"
39
+ :center="alertProps?.center"
40
+ :closable="alertProps?.closable"
41
+ :close-text="alertProps?.closeText"
42
+ :description="alertProps?.description"
43
+ >
44
+ <div v-if="alertProps?.html" v-html="alertProps?.html" />
45
+ </ElAlert>
46
+ </div>
47
+ </template>
48
+
49
49
  <style lang="scss" scoped>
50
50
  .global-alert {
51
51
  position: fixed;
@@ -1,16 +1,17 @@
1
1
  <script setup lang="ts" name="BlogApp">
2
2
  import Theme from 'vitepress/theme'
3
+ import { useBlogThemeMode } from '../composables/config/blog'
3
4
  import BlogHomeInfo from './BlogHomeInfo.vue'
4
5
  import BlogHomeBanner from './BlogHomeBanner.vue'
5
6
  import BlogList from './BlogList.vue'
6
7
  import BlogComment from './BlogComment.vue'
8
+
7
9
  // import BlogSearch from './BlogSearch.vue'
8
10
  import BlogSidebar from './BlogSidebar.vue'
9
11
  import BlogImagePreview from './BlogImagePreview.vue'
10
12
  import BlogArticleAnalyze from './BlogArticleAnalyze.vue'
11
13
  import BlogAlert from './BlogAlert.vue'
12
14
  import BlogPopover from './BlogPopover.vue'
13
- import { useBlogThemeMode } from '../composables/config/blog'
14
15
 
15
16
  const isBlogTheme = useBlogThemeMode()
16
17
  const { Layout } = Theme
@@ -39,7 +40,7 @@ const { Layout } = Theme
39
40
  <BlogSearch />
40
41
  </template> -->
41
42
  <!-- 自定义首页 -->
42
- <template #home-hero-before v-if="isBlogTheme">
43
+ <template v-if="isBlogTheme" #home-hero-before>
43
44
  <slot name="home-hero-before" />
44
45
  <div class="home">
45
46
  <div class="header-banner">
@@ -49,11 +50,13 @@ const { Layout } = Theme
49
50
  <div class="blog-list-wrapper">
50
51
  <BlogList />
51
52
  </div>
52
- <div class="blog-info-wrapper"><BlogHomeInfo /></div>
53
+ <div class="blog-info-wrapper">
54
+ <BlogHomeInfo />
55
+ </div>
53
56
  </div>
54
57
  </div>
55
58
  </template>
56
- <template #sidebar-nav-after v-if="isBlogTheme">
59
+ <template v-if="isBlogTheme" #sidebar-nav-after>
57
60
  <slot name="sidebar-nav-after" />
58
61
  <BlogSidebar />
59
62
  </template>
@@ -65,57 +68,86 @@ const { Layout } = Theme
65
68
 
66
69
  <!-- 透传默认主题的其它插槽 -->
67
70
  <!-- navbar -->
68
- <template #nav-bar-title-before
69
- ><slot name="nav-bar-title-before"
70
- /></template>
71
- <template #nav-bar-title-after
72
- ><slot name="nav-bar-title-after"
73
- /></template>
74
- <template #nav-bar-content-after
75
- ><slot name="nav-bar-content-after"
76
- /></template>
77
- <template #nav-screen-content-before
78
- ><slot name="nav-screen-content-before"
79
- /></template>
80
- <template #nav-screen-content-after
81
- ><slot name="nav-screen-content-after"
82
- /></template>
71
+ <template #nav-bar-title-before>
72
+ <slot name="nav-bar-title-before" />
73
+ </template>
74
+ <template #nav-bar-title-after>
75
+ <slot name="nav-bar-title-after" />
76
+ </template>
77
+ <template #nav-bar-content-after>
78
+ <slot name="nav-bar-content-after" />
79
+ </template>
80
+ <template #nav-screen-content-before>
81
+ <slot name="nav-screen-content-before" />
82
+ </template>
83
+ <template #nav-screen-content-after>
84
+ <slot name="nav-screen-content-after" />
85
+ </template>
83
86
 
84
87
  <!-- sidebar -->
85
- <template #sidebar-nav-before><slot name="sidebar-nav-before" /></template>
88
+ <template #sidebar-nav-before>
89
+ <slot name="sidebar-nav-before" />
90
+ </template>
86
91
 
87
92
  <!-- content -->
88
- <template #page-top><slot name="page-top" /></template>
89
- <template #page-bottom><slot name="page-bottom" /></template>
90
-
91
- <template #not-found><slot name="not-found" /></template>
92
- <template #home-hero-info><slot name="home-hero-info" /></template>
93
- <template #home-hero-image><slot name="home-hero-image" /></template>
94
- <template #home-hero-after><slot name="home-hero-after" /></template>
95
- <template #home-features-before
96
- ><slot name="home-features-before"
97
- /></template>
98
- <template #home-features-after
99
- ><slot name="home-features-after"
100
- /></template>
101
-
102
- <template #doc-footer-before><slot name="doc-footer-before" /></template>
103
-
104
- <template #doc-top><slot name="doc-top" /></template>
105
- <template #doc-bottom><slot name="doc-bottom" /></template>
106
-
107
- <template #aside-top><slot name="aside-top" /></template>
108
- <template #aside-bottom><slot name="aside-bottom" /></template>
109
- <template #aside-outline-before
110
- ><slot name="aside-outline-before"
111
- /></template>
112
- <template #aside-outline-after
113
- ><slot name="aside-outline-after"
114
- /></template>
115
- <template #aside-ads-before><slot name="aside-ads-before" /></template>
116
- <template #aside-ads-after><slot name="aside-ads-after" /></template>
93
+ <template #page-top>
94
+ <slot name="page-top" />
95
+ </template>
96
+ <template #page-bottom>
97
+ <slot name="page-bottom" />
98
+ </template>
99
+
100
+ <template #not-found>
101
+ <slot name="not-found" />
102
+ </template>
103
+ <template #home-hero-info>
104
+ <slot name="home-hero-info" />
105
+ </template>
106
+ <template #home-hero-image>
107
+ <slot name="home-hero-image" />
108
+ </template>
109
+ <template #home-hero-after>
110
+ <slot name="home-hero-after" />
111
+ </template>
112
+ <template #home-features-before>
113
+ <slot name="home-features-before" />
114
+ </template>
115
+ <template #home-features-after>
116
+ <slot name="home-features-after" />
117
+ </template>
118
+
119
+ <template #doc-footer-before>
120
+ <slot name="doc-footer-before" />
121
+ </template>
122
+
123
+ <template #doc-top>
124
+ <slot name="doc-top" />
125
+ </template>
126
+ <template #doc-bottom>
127
+ <slot name="doc-bottom" />
128
+ </template>
129
+
130
+ <template #aside-top>
131
+ <slot name="aside-top" />
132
+ </template>
133
+ <template #aside-bottom>
134
+ <slot name="aside-bottom" />
135
+ </template>
136
+ <template #aside-outline-before>
137
+ <slot name="aside-outline-before" />
138
+ </template>
139
+ <template #aside-outline-after>
140
+ <slot name="aside-outline-after" />
141
+ </template>
142
+ <template #aside-ads-before>
143
+ <slot name="aside-ads-before" />
144
+ </template>
145
+ <template #aside-ads-after>
146
+ <slot name="aside-ads-after" />
147
+ </template>
117
148
  </Layout>
118
149
  </template>
150
+
119
151
  <style scoped lang="scss">
120
152
  .home {
121
153
  margin: 0 auto;
@@ -1,47 +1,3 @@
1
- <template>
2
- <div class="doc-analyze" v-if="showAnalyze" data-pagefind-ignore="all">
3
- <span>
4
- <el-icon><EditPen /></el-icon>
5
- 字数:{{ wordCount }} 个字
6
- </span>
7
- <span>
8
- <el-icon><AlarmClock /></el-icon>
9
- 预计:{{ readTime }} 分钟
10
- </span>
11
- </div>
12
- <div class="meta-des" ref="$des" id="hack-article-des">
13
- <!-- TODO:是否需要原创?转载等标签,理论上可以添加标签解决,可以参考 charles7c -->
14
- <span v-if="author && !hiddenAuthor" class="author">
15
- <el-icon title="本文作者"><UserFilled /></el-icon>
16
- <a
17
- class="link"
18
- :href="currentAuthorInfo.url"
19
- :title="currentAuthorInfo.des"
20
- v-if="currentAuthorInfo"
21
- >
22
- {{ currentAuthorInfo.nickname }}
23
- </a>
24
- <template v-else>
25
- {{ author }}
26
- </template>
27
- </span>
28
- <span v-if="publishDate && !hiddenTime" class="publishDate">
29
- <el-icon :title="timeTitle"><Clock /></el-icon>
30
- {{ publishDate }}
31
- </span>
32
- <span v-if="tags.length" class="tags">
33
- <el-icon :title="timeTitle"><CollectionTag /></el-icon>
34
- <a class="link" :href="`/?tag=${tag}`" v-for="tag in tags" :key="tag"
35
- >{{ tag }}
36
- </a>
37
- </span>
38
- <!-- 封面展示 -->
39
- <ClientOnly>
40
- <BlogDocCover />
41
- </ClientOnly>
42
- </div>
43
- </template>
44
-
45
1
  <script lang="ts" setup>
46
2
  // 阅读时间计算方式参考
47
3
  // https://zhuanlan.zhihu.com/p/36375802
@@ -49,15 +5,15 @@ import { useData, useRoute } from 'vitepress'
49
5
  import { computed, onMounted, ref, watch } from 'vue'
50
6
  import { ElIcon } from 'element-plus'
51
7
  import {
52
- UserFilled,
8
+ AlarmClock,
53
9
  Clock,
10
+ CollectionTag,
54
11
  EditPen,
55
- AlarmClock,
56
- CollectionTag
12
+ UserFilled
57
13
  } from '@element-plus/icons-vue'
58
14
  import { useBlogConfig, useCurrentArticle } from '../composables/config/blog'
59
15
  import countWord, { formatShowDate } from '../utils/client'
60
- import { Theme } from '../composables/config'
16
+ import type { Theme } from '../composables/config'
61
17
  import BlogDocCover from './BlogDocCover.vue'
62
18
 
63
19
  const { article, authorList } = useBlogConfig()
@@ -69,7 +25,7 @@ const tags = computed(() => {
69
25
  []
70
26
  .concat(tag, tags, categories)
71
27
  .flat()
72
- .filter((v) => !!v)
28
+ .filter(v => !!v)
73
29
  )
74
30
  ]
75
31
  })
@@ -99,20 +55,20 @@ const readTime = computed(() => {
99
55
  const route = useRoute()
100
56
  const $des = ref<HTMLDivElement>()
101
57
 
102
- const analyze = () => {
58
+ function analyze() {
103
59
  if (!$des.value) {
104
60
  return
105
61
  }
106
- document.querySelectorAll('.meta-des').forEach((v) => v.remove())
62
+ document.querySelectorAll('.meta-des').forEach(v => v.remove())
107
63
  const docDomContainer = window.document.querySelector('#VPContent')
108
64
  const imgs = docDomContainer?.querySelectorAll<HTMLImageElement>(
109
65
  '.content-container .main img'
110
66
  )
111
67
  imageCount.value = imgs?.length || 0
112
68
 
113
- const words =
114
- docDomContainer?.querySelector('.content-container .main')?.textContent ||
115
- ''
69
+ const words
70
+ = docDomContainer?.querySelector('.content-container .main')?.textContent
71
+ || ''
116
72
 
117
73
  wordCount.value = countWord(words)
118
74
  docDomContainer?.querySelector('h1')?.after($des.value!)
@@ -151,11 +107,11 @@ const { theme } = useData<Theme.Config>()
151
107
  const globalAuthor = computed(() => theme.value.blog?.author || '')
152
108
  const author = computed(
153
109
  () =>
154
- (frontmatter.value.author || currentArticle.value?.meta.author) ??
155
- globalAuthor.value
110
+ (frontmatter.value.author || currentArticle.value?.meta.author)
111
+ ?? globalAuthor.value
156
112
  )
157
113
  const currentAuthorInfo = computed(() =>
158
- authorList?.find((v) => author.value === v.nickname)
114
+ authorList?.find(v => author.value === v.nickname)
159
115
  )
160
116
  const hiddenAuthor = computed(() => frontmatter.value.author === false)
161
117
 
@@ -171,6 +127,49 @@ watch(
171
127
  )
172
128
  </script>
173
129
 
130
+ <template>
131
+ <div v-if="showAnalyze" class="doc-analyze" data-pagefind-ignore="all">
132
+ <span>
133
+ <ElIcon><EditPen /></ElIcon>
134
+ 字数:{{ wordCount }} 个字
135
+ </span>
136
+ <span>
137
+ <ElIcon><AlarmClock /></ElIcon>
138
+ 预计:{{ readTime }} 分钟
139
+ </span>
140
+ </div>
141
+ <div id="hack-article-des" ref="$des" class="meta-des">
142
+ <!-- TODO:是否需要原创?转载等标签,理论上可以添加标签解决,可以参考 charles7c -->
143
+ <span v-if="author && !hiddenAuthor" class="author">
144
+ <ElIcon title="本文作者"><UserFilled /></ElIcon>
145
+ <a
146
+ v-if="currentAuthorInfo"
147
+ class="link"
148
+ :href="currentAuthorInfo.url"
149
+ :title="currentAuthorInfo.des"
150
+ >
151
+ {{ currentAuthorInfo.nickname }}
152
+ </a>
153
+ <template v-else>
154
+ {{ author }}
155
+ </template>
156
+ </span>
157
+ <span v-if="publishDate && !hiddenTime" class="publishDate">
158
+ <ElIcon :title="timeTitle"><Clock /></ElIcon>
159
+ {{ publishDate }}
160
+ </span>
161
+ <span v-if="tags.length" class="tags">
162
+ <ElIcon :title="timeTitle"><CollectionTag /></ElIcon>
163
+ <a v-for="tag in tags" :key="tag" class="link" :href="`/?tag=${tag}`">{{ tag }}
164
+ </a>
165
+ </span>
166
+ <!-- 封面展示 -->
167
+ <ClientOnly>
168
+ <BlogDocCover />
169
+ </ClientOnly>
170
+ </div>
171
+ </template>
172
+
174
173
  <style lang="scss" scoped>
175
174
  .doc-analyze {
176
175
  color: var(--vp-c-text-2);