@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 +2 -1
- package/node.js +27 -21
- package/package.json +23 -23
- package/src/components/BlogAlert.vue +17 -17
- package/src/components/BlogApp.vue +81 -49
- package/src/components/BlogArticleAnalyze.vue +56 -57
- package/src/components/BlogComment.vue +53 -50
- package/src/components/BlogDocCover.vue +4 -4
- package/src/components/BlogFriendLink.vue +40 -31
- package/src/components/BlogHomeBanner.vue +22 -16
- package/src/components/BlogHomeOverview.vue +20 -20
- package/src/components/BlogHomeTags.vue +49 -40
- package/src/components/BlogHotArticle.vue +43 -36
- package/src/components/BlogImagePreview.vue +7 -5
- package/src/components/BlogItem.vue +42 -43
- package/src/components/BlogList.vue +46 -42
- package/src/components/BlogPopover.vue +41 -39
- package/src/components/BlogRecommendArticle.vue +58 -48
- package/src/components/BlogSearch.vue +143 -145
- package/src/components/UserWorks.vue +214 -210
- package/src/composables/config/blog.ts +7 -5
- package/src/composables/config/index.ts +34 -31
- package/src/constants/svg.ts +2 -2
- package/src/index.ts +1 -2
- package/src/node.ts +2 -2
- package/src/styles/scss/global.scss +0 -5
- package/src/utils/client/index.ts +9 -8
- package/src/utils/node/genFeed.ts +8 -7
- package/src/utils/node/index.ts +8 -6
- package/src/utils/node/mdPlugins.ts +29 -22
- package/src/utils/node/theme.ts +21 -15
- package/src/utils/node/vitePlugins.ts +7 -6
- package/types/vue-shim.d.ts +1 -1
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
|
|
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,
|
|
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,
|
|
281
|
-
return `${base}${
|
|
280
|
+
function joinPath(base, path4) {
|
|
281
|
+
return `${base}${path4}`.replace(/\/+/g, "/");
|
|
282
282
|
}
|
|
283
|
-
function withBase(base,
|
|
284
|
-
return EXTERNAL_URL_RE.test(
|
|
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 ||
|
|
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
|
-
`^\\.\\/${
|
|
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
|
-
`^${
|
|
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 =
|
|
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:
|
|
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
|
|
457
|
-
var
|
|
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 =
|
|
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 =
|
|
520
|
-
(0,
|
|
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.
|
|
3
|
+
"version": "0.1.50",
|
|
4
4
|
"description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
|
|
5
|
-
"
|
|
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
|
-
"
|
|
16
|
-
"types",
|
|
30
|
+
"node.d.ts",
|
|
17
31
|
"node.js",
|
|
18
|
-
"
|
|
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.
|
|
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 {
|
|
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
|
|
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"
|
|
53
|
+
<div class="blog-info-wrapper">
|
|
54
|
+
<BlogHomeInfo />
|
|
55
|
+
</div>
|
|
53
56
|
</div>
|
|
54
57
|
</div>
|
|
55
58
|
</template>
|
|
56
|
-
<template
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
<template #nav-bar-title-after
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<template #nav-bar-content-after
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
<template #nav-screen-content-before
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<template #nav-screen-content-after
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|
88
|
+
<template #sidebar-nav-before>
|
|
89
|
+
<slot name="sidebar-nav-before" />
|
|
90
|
+
</template>
|
|
86
91
|
|
|
87
92
|
<!-- content -->
|
|
88
|
-
<template #page-top
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<template #
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<template #
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<template #home-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
<template #
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
<template #
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
8
|
+
AlarmClock,
|
|
53
9
|
Clock,
|
|
10
|
+
CollectionTag,
|
|
54
11
|
EditPen,
|
|
55
|
-
|
|
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(
|
|
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
|
-
|
|
58
|
+
function analyze() {
|
|
103
59
|
if (!$des.value) {
|
|
104
60
|
return
|
|
105
61
|
}
|
|
106
|
-
document.querySelectorAll('.meta-des').forEach(
|
|
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(
|
|
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);
|