@sugarat/theme 0.2.1 → 0.2.2
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 +3 -35
- package/node.js +33 -137
- package/package.json +5 -8
- package/src/composables/config/index.ts +4 -35
- package/src/index.ts +2 -0
- package/src/node.ts +6 -7
- package/src/utils/node/mdPlugins.ts +26 -18
- package/src/utils/node/theme.ts +0 -16
- package/src/utils/node/vitePlugins.ts +12 -2
- package/src/utils/node/genFeed.ts +0 -95
package/node.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { DefaultTheme, UserConfig } from 'vitepress';
|
|
2
2
|
import { ElButton } from 'element-plus';
|
|
3
|
-
import {
|
|
3
|
+
import { RSSOptions } from 'vitepress-plugin-rss';
|
|
4
4
|
export { tabsMarkdownPlugin } from 'vitepress-plugin-tabs';
|
|
5
5
|
|
|
6
|
+
type RSSPluginOptions = RSSOptions;
|
|
6
7
|
declare namespace BlogPopover {
|
|
7
8
|
interface Title {
|
|
8
9
|
type: 'title';
|
|
@@ -273,40 +274,7 @@ declare namespace Theme {
|
|
|
273
274
|
*/
|
|
274
275
|
footer?: Footer;
|
|
275
276
|
}
|
|
276
|
-
type RSSOptions =
|
|
277
|
-
id?: string;
|
|
278
|
-
/**
|
|
279
|
-
* 你的站点地址
|
|
280
|
-
* @example 'https://sugarat.top'
|
|
281
|
-
*/
|
|
282
|
-
baseUrl: string;
|
|
283
|
-
/**
|
|
284
|
-
* 线上访问的RSS地址
|
|
285
|
-
* @default
|
|
286
|
-
* @example https://sugarat.top/feed.rss
|
|
287
|
-
* ```ts
|
|
288
|
-
* `${baseUrl + VPConfig.site.base + (filename || 'feed.rss'}`
|
|
289
|
-
* ```
|
|
290
|
-
*/
|
|
291
|
-
url?: string;
|
|
292
|
-
/**
|
|
293
|
-
* 输出的RSS文件名
|
|
294
|
-
* @default 'feed.rss'
|
|
295
|
-
*/
|
|
296
|
-
filename?: string;
|
|
297
|
-
/**
|
|
298
|
-
* RSS的图标展示
|
|
299
|
-
* @default true
|
|
300
|
-
*/
|
|
301
|
-
icon?: boolean;
|
|
302
|
-
/**
|
|
303
|
-
* 限制输出文件包含的文章数量
|
|
304
|
-
* @default 0
|
|
305
|
-
* @description (0 不限制;> 1 会按照日期排序对输出内容进行调整)
|
|
306
|
-
*/
|
|
307
|
-
limit?: number;
|
|
308
|
-
ariaLabel?: string;
|
|
309
|
-
};
|
|
277
|
+
type RSSOptions = RSSPluginOptions;
|
|
310
278
|
interface Footer {
|
|
311
279
|
/**
|
|
312
280
|
* 自定义补充信息
|
package/node.js
CHANGED
|
@@ -18,6 +18,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
return to;
|
|
19
19
|
};
|
|
20
20
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
25
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
26
|
mod
|
|
23
27
|
));
|
|
@@ -206,12 +210,19 @@ function formatDate(d, fmt = "yyyy-MM-dd hh:mm:ss") {
|
|
|
206
210
|
}
|
|
207
211
|
const o = {
|
|
208
212
|
"M+": d.getMonth() + 1,
|
|
213
|
+
// 月份
|
|
209
214
|
"d+": d.getDate(),
|
|
215
|
+
// 日
|
|
210
216
|
"h+": d.getHours(),
|
|
217
|
+
// 小时
|
|
211
218
|
"m+": d.getMinutes(),
|
|
219
|
+
// 分
|
|
212
220
|
"s+": d.getSeconds(),
|
|
221
|
+
// 秒
|
|
213
222
|
"q+": Math.floor((d.getMonth() + 3) / 3),
|
|
223
|
+
// 季度
|
|
214
224
|
"S": d.getMilliseconds()
|
|
225
|
+
// 毫秒
|
|
215
226
|
};
|
|
216
227
|
if (/(y+)/.test(fmt)) {
|
|
217
228
|
fmt = fmt.replace(
|
|
@@ -256,7 +267,7 @@ function getDefaultTitle(content) {
|
|
|
256
267
|
return title;
|
|
257
268
|
}
|
|
258
269
|
function getFileBirthTime(url) {
|
|
259
|
-
let date = new Date();
|
|
270
|
+
let date = /* @__PURE__ */ new Date();
|
|
260
271
|
try {
|
|
261
272
|
const infoStr = (0, import_node_child_process.spawnSync)("git", ["log", "-1", '--pretty="%ci"', url]).stdout?.toString().replace(/["']/g, "").trim();
|
|
262
273
|
if (infoStr) {
|
|
@@ -276,18 +287,11 @@ function aliasObjectToArray(obj) {
|
|
|
276
287
|
replacement
|
|
277
288
|
}));
|
|
278
289
|
}
|
|
279
|
-
var EXTERNAL_URL_RE = /^[a-z]+:/i;
|
|
280
|
-
function joinPath(base, path4) {
|
|
281
|
-
return `${base}${path4}`.replace(/\/+/g, "/");
|
|
282
|
-
}
|
|
283
|
-
function withBase(base, path4) {
|
|
284
|
-
return EXTERNAL_URL_RE.test(path4) || path4.startsWith(".") ? path4 : joinPath(base, path4);
|
|
285
|
-
}
|
|
286
290
|
|
|
287
291
|
// src/utils/node/mdPlugins.ts
|
|
288
292
|
function getMarkdownPlugins(cfg) {
|
|
289
293
|
const markdownPlugin = [];
|
|
290
|
-
if (cfg?.tabs) {
|
|
294
|
+
if (cfg?.tabs !== false) {
|
|
291
295
|
markdownPlugin.push(tabsPlugin);
|
|
292
296
|
}
|
|
293
297
|
if (cfg) {
|
|
@@ -310,15 +314,7 @@ function registerMdPlugins(vpCfg, plugins) {
|
|
|
310
314
|
};
|
|
311
315
|
}
|
|
312
316
|
}
|
|
313
|
-
function
|
|
314
|
-
if (!config?.mermaid)
|
|
315
|
-
return;
|
|
316
|
-
if (!config.vite)
|
|
317
|
-
config.vite = {};
|
|
318
|
-
if (!config.vite.plugins)
|
|
319
|
-
config.vite.plugins = [];
|
|
320
|
-
const { MermaidPlugin } = require("vitepress-plugin-mermaid");
|
|
321
|
-
config.vite.plugins.push(MermaidPlugin(config.mermaid));
|
|
317
|
+
function patchMermaidPluginCfg(config) {
|
|
322
318
|
if (!config.vite.resolve)
|
|
323
319
|
config.vite.resolve = {};
|
|
324
320
|
if (!config.vite.resolve.alias)
|
|
@@ -332,31 +328,12 @@ function assignMermaid(config) {
|
|
|
332
328
|
{ find: /^dayjs\/(.*).js/, replacement: "dayjs/esm/$1" }
|
|
333
329
|
];
|
|
334
330
|
}
|
|
335
|
-
function
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
...config,
|
|
339
|
-
mermaid: extendThemeConfig.mermaid === true ? {} : extendThemeConfig.mermaid
|
|
340
|
-
};
|
|
341
|
-
assignMermaid(resultConfig);
|
|
342
|
-
return resultConfig;
|
|
343
|
-
}
|
|
344
|
-
function supportRunExtendsPlugin(config) {
|
|
345
|
-
if (!config.markdown)
|
|
346
|
-
config.markdown = {};
|
|
347
|
-
if (config.extends?.markdown?.config) {
|
|
348
|
-
const markdownExtendsConfigOriginal = config.extends?.markdown?.config;
|
|
349
|
-
const selfMarkdownConfig = config.markdown?.config;
|
|
350
|
-
config.markdown.config = (...rest) => {
|
|
351
|
-
selfMarkdownConfig?.(...rest);
|
|
352
|
-
markdownExtendsConfigOriginal?.(...rest);
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
const inlineConfig = config.extends;
|
|
356
|
-
if (inlineConfig.themeConfig?.blog?.RSS && inlineConfig.themeConfig?.blog?.RSS?.icon !== false && inlineConfig.themeConfig?.socialLinks?.length && !inlineConfig.themeConfig?.socialLinks?.[0].link) {
|
|
357
|
-
const { RSS } = inlineConfig.themeConfig?.blog;
|
|
358
|
-
inlineConfig.themeConfig.socialLinks[0].link = `${RSS.baseUrl}${(config.base || "/") + (RSS.filename || "feed.rss")}`;
|
|
331
|
+
function patchOptimizeDeps(config) {
|
|
332
|
+
if (!config.vite.optimizeDeps) {
|
|
333
|
+
config.vite.optimizeDeps = {};
|
|
359
334
|
}
|
|
335
|
+
config.vite.optimizeDeps.exclude = ["vitepress-plugin-tabs", "@sugarat/theme"];
|
|
336
|
+
config.vite.optimizeDeps.include = ["element-plus"];
|
|
360
337
|
}
|
|
361
338
|
|
|
362
339
|
// src/utils/node/theme.ts
|
|
@@ -412,7 +389,7 @@ function getArticles(cfg) {
|
|
|
412
389
|
} else {
|
|
413
390
|
const timeZone = cfg?.timeZone ?? 8;
|
|
414
391
|
meta.date = formatDate(
|
|
415
|
-
new Date(`${new Date(meta.date).toUTCString()}+${timeZone}`)
|
|
392
|
+
/* @__PURE__ */ new Date(`${new Date(meta.date).toUTCString()}+${timeZone}`)
|
|
416
393
|
);
|
|
417
394
|
}
|
|
418
395
|
meta.categories = typeof meta.categories === "string" ? [meta.categories] : meta.categories;
|
|
@@ -434,105 +411,17 @@ function getArticles(cfg) {
|
|
|
434
411
|
}).filter((v) => v.meta.layout !== "home");
|
|
435
412
|
return data;
|
|
436
413
|
}
|
|
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>';
|
|
438
414
|
function patchVPThemeConfig(cfg, vpThemeConfig = {}) {
|
|
439
|
-
const RSS = cfg?.RSS;
|
|
440
|
-
if (RSS && RSS.icon !== false) {
|
|
441
|
-
vpThemeConfig.socialLinks = [
|
|
442
|
-
{
|
|
443
|
-
icon: {
|
|
444
|
-
svg: svgIcon
|
|
445
|
-
},
|
|
446
|
-
link: RSS?.url,
|
|
447
|
-
ariaLabel: RSS?.ariaLabel || "RSS"
|
|
448
|
-
}
|
|
449
|
-
];
|
|
450
|
-
}
|
|
451
415
|
vpThemeConfig.sidebar = patchDefaultThemeSideBar(cfg)?.sidebar;
|
|
452
416
|
return vpThemeConfig;
|
|
453
417
|
}
|
|
454
418
|
|
|
455
419
|
// src/utils/node/vitePlugins.ts
|
|
456
|
-
var
|
|
420
|
+
var import_node_path2 = __toESM(require("path"));
|
|
457
421
|
var import_node_child_process2 = require("child_process");
|
|
458
422
|
var import_node_process2 = __toESM(require("process"));
|
|
459
423
|
var import_vitepress_plugin_pagefind = require("vitepress-plugin-pagefind");
|
|
460
|
-
|
|
461
|
-
// src/utils/node/genFeed.ts
|
|
462
|
-
var import_node_path2 = __toESM(require("path"));
|
|
463
|
-
var import_node_fs2 = __toESM(require("fs"));
|
|
464
|
-
var import_feed = require("feed");
|
|
465
|
-
async function genFeed(config) {
|
|
466
|
-
const blogCfg = config.userConfig.themeConfig.blog;
|
|
467
|
-
let posts = blogCfg.pagesData;
|
|
468
|
-
const { RSS, authorList = [] } = blogCfg;
|
|
469
|
-
if (!RSS)
|
|
470
|
-
return;
|
|
471
|
-
const { createMarkdownRenderer } = await import("vitepress");
|
|
472
|
-
const mdRender = await createMarkdownRenderer(
|
|
473
|
-
config.srcDir,
|
|
474
|
-
config.markdown,
|
|
475
|
-
config.site.base,
|
|
476
|
-
config.logger
|
|
477
|
-
);
|
|
478
|
-
console.log();
|
|
479
|
-
console.log("=== feed: https://github.com/jpmonette/feed ===");
|
|
480
|
-
const { base } = config.userConfig;
|
|
481
|
-
const { baseUrl, filename } = RSS;
|
|
482
|
-
const feed = new import_feed.Feed({
|
|
483
|
-
id: baseUrl,
|
|
484
|
-
link: baseUrl,
|
|
485
|
-
...RSS
|
|
486
|
-
});
|
|
487
|
-
posts.sort(
|
|
488
|
-
(a, b) => +new Date(b.meta.date) - +new Date(a.meta.date)
|
|
489
|
-
);
|
|
490
|
-
posts = posts.filter((v) => v.meta.layout !== "home").filter((v) => v.meta.hidden !== true);
|
|
491
|
-
if (void 0 !== RSS?.limit && RSS?.limit > 0) {
|
|
492
|
-
posts.splice(RSS.limit);
|
|
493
|
-
}
|
|
494
|
-
for (const { route, meta } of posts) {
|
|
495
|
-
const { title, description, date } = meta;
|
|
496
|
-
const author = meta.author ?? blogCfg.author;
|
|
497
|
-
let link = `${baseUrl}${withBase(
|
|
498
|
-
base || "",
|
|
499
|
-
route.replace(/(^|\/)index$/, "$1")
|
|
500
|
-
)}`;
|
|
501
|
-
link = link.endsWith("/") ? link : `${link}${config?.cleanUrls ? "" : ".html"}`;
|
|
502
|
-
const authorLink = authorList.find((v) => v.nickname === author)?.url;
|
|
503
|
-
let html;
|
|
504
|
-
const filepath = pageMap.get(route);
|
|
505
|
-
if (filepath) {
|
|
506
|
-
const fileContent = import_node_fs2.default.readFileSync(filepath, "utf-8");
|
|
507
|
-
html = mdRender.render(fileContent);
|
|
508
|
-
}
|
|
509
|
-
feed.addItem({
|
|
510
|
-
title,
|
|
511
|
-
id: link,
|
|
512
|
-
link,
|
|
513
|
-
description,
|
|
514
|
-
content: html,
|
|
515
|
-
author: [
|
|
516
|
-
{
|
|
517
|
-
name: author,
|
|
518
|
-
link: authorLink
|
|
519
|
-
}
|
|
520
|
-
],
|
|
521
|
-
date: new Date(date)
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
const RSSFilename = filename || "feed.rss";
|
|
525
|
-
const RSSFile = import_node_path2.default.join(config.outDir, RSSFilename);
|
|
526
|
-
(0, import_node_fs2.writeFileSync)(RSSFile, feed.rss2());
|
|
527
|
-
console.log("\u{1F389} RSS generated", RSSFilename);
|
|
528
|
-
console.log("rss filepath:", RSSFile);
|
|
529
|
-
console.log("rss url:", `${baseUrl}${config.site.base + RSSFilename}`);
|
|
530
|
-
console.log("include", posts.length, "posts");
|
|
531
|
-
console.log();
|
|
532
|
-
console.log();
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
// src/utils/node/vitePlugins.ts
|
|
424
|
+
var import_vitepress_plugin_rss = require("vitepress-plugin-rss");
|
|
536
425
|
function getVitePlugins(cfg) {
|
|
537
426
|
const plugins = [];
|
|
538
427
|
const buildEndFn = [];
|
|
@@ -543,7 +432,13 @@ function getVitePlugins(cfg) {
|
|
|
543
432
|
(0, import_vitepress_plugin_pagefind.pagefindPlugin)({ ...ops, customSearchQuery: import_vitepress_plugin_pagefind.chineseSearchOptimize })
|
|
544
433
|
);
|
|
545
434
|
}
|
|
546
|
-
|
|
435
|
+
if (cfg?.mermaid !== false) {
|
|
436
|
+
const { MermaidPlugin } = require("vitepress-plugin-mermaid");
|
|
437
|
+
plugins.push(MermaidPlugin(cfg?.mermaid === true ? {} : cfg?.mermaid ?? {}));
|
|
438
|
+
}
|
|
439
|
+
if (cfg?.RSS) {
|
|
440
|
+
plugins.push((0, import_vitepress_plugin_rss.RssPlugin)(cfg.RSS));
|
|
441
|
+
}
|
|
547
442
|
return plugins;
|
|
548
443
|
}
|
|
549
444
|
function registerVitePlugins(vpCfg, plugins) {
|
|
@@ -582,21 +477,22 @@ function getThemeConfig(cfg) {
|
|
|
582
477
|
registerVitePlugins(extraVPConfig, vitePlugins);
|
|
583
478
|
const markdownPlugin = getMarkdownPlugins(cfg);
|
|
584
479
|
registerMdPlugins(extraVPConfig, markdownPlugin);
|
|
480
|
+
patchMermaidPluginCfg(extraVPConfig);
|
|
481
|
+
patchOptimizeDeps(extraVPConfig);
|
|
585
482
|
return {
|
|
586
483
|
themeConfig: {
|
|
587
484
|
blog: {
|
|
588
485
|
pagesData,
|
|
589
486
|
...cfg
|
|
590
487
|
},
|
|
488
|
+
// 补充一些额外的配置用于继承
|
|
591
489
|
...patchVPThemeConfig(cfg)
|
|
592
490
|
},
|
|
593
491
|
...extraVPConfig
|
|
594
492
|
};
|
|
595
493
|
}
|
|
596
494
|
function defineConfig(config) {
|
|
597
|
-
|
|
598
|
-
supportRunExtendsPlugin(resultConfig);
|
|
599
|
-
return resultConfig;
|
|
495
|
+
return config;
|
|
600
496
|
}
|
|
601
497
|
// Annotate the CommonJS export names for ESM import in node:
|
|
602
498
|
0 && (module.exports = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sugarat/theme",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
|
|
5
5
|
"author": "sugar",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,32 +38,29 @@
|
|
|
38
38
|
"@vue/shared": "^3.2.45",
|
|
39
39
|
"@vueuse/core": "^9.6.0",
|
|
40
40
|
"fast-glob": "^3.2.12",
|
|
41
|
-
"feed": "^4.2.2",
|
|
42
41
|
"gray-matter": "^4.0.3",
|
|
43
|
-
"highlight.js": "^11.7.0",
|
|
44
42
|
"mermaid": "^10.2.4",
|
|
45
43
|
"vitepress-plugin-mermaid": "^2.0.13",
|
|
46
44
|
"vitepress-plugin-pagefind": "0.2.10",
|
|
47
|
-
"
|
|
45
|
+
"vitepress-plugin-rss": "0.1.2",
|
|
46
|
+
"vitepress-plugin-tabs": "0.2.0"
|
|
48
47
|
},
|
|
49
48
|
"devDependencies": {
|
|
50
49
|
"@element-plus/icons-vue": "^2.1.0",
|
|
51
50
|
"element-plus": "^2.3.4",
|
|
52
51
|
"pagefind": "1.0.3",
|
|
53
52
|
"sass": "^1.56.1",
|
|
54
|
-
"tsup": " ^6.5.0",
|
|
55
53
|
"typescript": "^4.8.2",
|
|
56
54
|
"vitepress": "1.0.0-rc.17",
|
|
57
|
-
"vitepress-plugin-tabs": "^0.2.0",
|
|
58
55
|
"vue": "^3.3.4"
|
|
59
56
|
},
|
|
60
57
|
"scripts": {
|
|
61
58
|
"dev": "npm run build:node && npm run dev:docs",
|
|
62
59
|
"dev:docs": "vitepress dev docs",
|
|
63
|
-
"dev:node": "npx tsup
|
|
60
|
+
"dev:node": "npx tsup",
|
|
64
61
|
"build": "npm run build:node && npm run build:docs",
|
|
65
62
|
"build:docs": "vitepress build docs",
|
|
66
|
-
"build:node": "npx tsup
|
|
63
|
+
"build:node": "npx tsup",
|
|
67
64
|
"serve": "vitepress serve docs"
|
|
68
65
|
}
|
|
69
66
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/* eslint-disable ts/no-namespace */
|
|
2
2
|
import type { ElButton } from 'element-plus'
|
|
3
3
|
import type { DefaultTheme } from 'vitepress'
|
|
4
|
-
import type {
|
|
4
|
+
import type { RSSOptions } from 'vitepress-plugin-rss'
|
|
5
|
+
|
|
6
|
+
type RSSPluginOptions = RSSOptions
|
|
5
7
|
|
|
6
8
|
// TODO: 重构 lint 问题
|
|
7
9
|
export declare namespace BlogPopover {
|
|
@@ -304,40 +306,7 @@ export namespace Theme {
|
|
|
304
306
|
footer?: Footer
|
|
305
307
|
}
|
|
306
308
|
|
|
307
|
-
export type RSSOptions =
|
|
308
|
-
id?: string
|
|
309
|
-
/**
|
|
310
|
-
* 你的站点地址
|
|
311
|
-
* @example 'https://sugarat.top'
|
|
312
|
-
*/
|
|
313
|
-
baseUrl: string
|
|
314
|
-
/**
|
|
315
|
-
* 线上访问的RSS地址
|
|
316
|
-
* @default
|
|
317
|
-
* @example https://sugarat.top/feed.rss
|
|
318
|
-
* ```ts
|
|
319
|
-
* `${baseUrl + VPConfig.site.base + (filename || 'feed.rss'}`
|
|
320
|
-
* ```
|
|
321
|
-
*/
|
|
322
|
-
url?: string
|
|
323
|
-
/**
|
|
324
|
-
* 输出的RSS文件名
|
|
325
|
-
* @default 'feed.rss'
|
|
326
|
-
*/
|
|
327
|
-
filename?: string
|
|
328
|
-
/**
|
|
329
|
-
* RSS的图标展示
|
|
330
|
-
* @default true
|
|
331
|
-
*/
|
|
332
|
-
icon?: boolean
|
|
333
|
-
/**
|
|
334
|
-
* 限制输出文件包含的文章数量
|
|
335
|
-
* @default 0
|
|
336
|
-
* @description (0 不限制;> 1 会按照日期排序对输出内容进行调整)
|
|
337
|
-
*/
|
|
338
|
-
limit?: number
|
|
339
|
-
ariaLabel?: string
|
|
340
|
-
}
|
|
309
|
+
export type RSSOptions = RSSPluginOptions
|
|
341
310
|
|
|
342
311
|
export interface Footer {
|
|
343
312
|
/**
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import 'element-plus/theme-chalk/dark/css-vars.css'
|
|
|
7
7
|
|
|
8
8
|
import type { Theme } from 'vitepress'
|
|
9
9
|
import DefaultTheme from 'vitepress/theme'
|
|
10
|
+
import { enhanceAppWithTabs } from 'vitepress-plugin-tabs/client'
|
|
10
11
|
import BlogApp from './components/BlogApp.vue'
|
|
11
12
|
import { withConfigProvider } from './composables/config/blog'
|
|
12
13
|
|
|
@@ -21,6 +22,7 @@ export const BlogTheme: Theme = {
|
|
|
21
22
|
...DefaultTheme,
|
|
22
23
|
Layout: withConfigProvider(BlogApp),
|
|
23
24
|
enhanceApp(ctx) {
|
|
25
|
+
enhanceAppWithTabs(ctx.app)
|
|
24
26
|
DefaultTheme.enhanceApp(ctx)
|
|
25
27
|
ctx.app.component('TimelinePage', TimelinePage)
|
|
26
28
|
ctx.app.component('UserWorksPage', UserWorksPage)
|
package/src/node.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
/* eslint-disable global-require */
|
|
2
|
-
/* eslint-disable prefer-rest-params */
|
|
3
1
|
import type { UserConfig } from 'vitepress'
|
|
4
2
|
import type { Theme } from './composables/config/index'
|
|
5
3
|
import {
|
|
6
4
|
getMarkdownPlugins,
|
|
5
|
+
patchMermaidPluginCfg,
|
|
6
|
+
patchOptimizeDeps,
|
|
7
7
|
registerMdPlugins,
|
|
8
|
-
supportRunExtendsPlugin,
|
|
9
|
-
wrapperCfgWithMermaid
|
|
10
8
|
} from './utils/node/mdPlugins'
|
|
11
9
|
import { getArticles, patchVPThemeConfig } from './utils/node/theme'
|
|
12
10
|
import { getVitePlugins, registerVitePlugins } from './utils/node/vitePlugins'
|
|
@@ -30,6 +28,9 @@ export function getThemeConfig(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
30
28
|
// 注册markdown插件
|
|
31
29
|
registerMdPlugins(extraVPConfig, markdownPlugin)
|
|
32
30
|
|
|
31
|
+
// patch extraVPConfig
|
|
32
|
+
patchMermaidPluginCfg(extraVPConfig)
|
|
33
|
+
patchOptimizeDeps(extraVPConfig)
|
|
33
34
|
return {
|
|
34
35
|
themeConfig: {
|
|
35
36
|
blog: {
|
|
@@ -47,9 +48,7 @@ export function getThemeConfig(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
47
48
|
* defineConfig Helper
|
|
48
49
|
*/
|
|
49
50
|
export function defineConfig(config: UserConfig<Theme.Config>): any {
|
|
50
|
-
|
|
51
|
-
supportRunExtendsPlugin(resultConfig)
|
|
52
|
-
return resultConfig
|
|
51
|
+
return config
|
|
53
52
|
}
|
|
54
53
|
|
|
55
54
|
// 重新导包 tabsMarkdownPlugin 导出CJS格式支持
|
|
@@ -6,8 +6,8 @@ import { aliasObjectToArray } from './index'
|
|
|
6
6
|
|
|
7
7
|
export function getMarkdownPlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
8
8
|
const markdownPlugin: any[] = []
|
|
9
|
-
// tabs
|
|
10
|
-
if (cfg?.tabs) {
|
|
9
|
+
// tabs支持,默认开启
|
|
10
|
+
if (cfg?.tabs !== false) {
|
|
11
11
|
markdownPlugin.push(tabsMarkdownPlugin)
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -62,8 +62,31 @@ export function assignMermaid(config: any) {
|
|
|
62
62
|
]
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
export function patchMermaidPluginCfg(config: any) {
|
|
66
|
+
if (!config.vite.resolve)
|
|
67
|
+
config.vite.resolve = {}
|
|
68
|
+
if (!config.vite.resolve.alias)
|
|
69
|
+
config.vite.resolve.alias = {}
|
|
70
|
+
|
|
71
|
+
config.vite.resolve.alias = [
|
|
72
|
+
...aliasObjectToArray({
|
|
73
|
+
...config.vite.resolve.alias,
|
|
74
|
+
'cytoscape/dist/cytoscape.umd.js': 'cytoscape/dist/cytoscape.esm.js',
|
|
75
|
+
'mermaid': 'mermaid/dist/mermaid.esm.mjs'
|
|
76
|
+
}),
|
|
77
|
+
{ find: /^dayjs\/(.*).js/, replacement: 'dayjs/esm/$1' }
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function patchOptimizeDeps(config: any) {
|
|
82
|
+
if (!config.vite.optimizeDeps) {
|
|
83
|
+
config.vite.optimizeDeps = {}
|
|
84
|
+
}
|
|
85
|
+
config.vite.optimizeDeps.exclude = ['vitepress-plugin-tabs', '@sugarat/theme']
|
|
86
|
+
config.vite.optimizeDeps.include = ['element-plus']
|
|
87
|
+
}
|
|
88
|
+
|
|
65
89
|
export function wrapperCfgWithMermaid(config: UserConfig<Theme.Config>): any {
|
|
66
|
-
// eslint-disable-next-line ts/ban-ts-comment
|
|
67
90
|
// @ts-expect-error
|
|
68
91
|
const extendThemeConfig = (config.extends?.themeConfig?.blog
|
|
69
92
|
|| {}) as Theme.BlogConfig
|
|
@@ -99,19 +122,4 @@ export function supportRunExtendsPlugin(config: UserConfig<Theme.Config>) {
|
|
|
99
122
|
markdownExtendsConfigOriginal?.(...rest)
|
|
100
123
|
}
|
|
101
124
|
}
|
|
102
|
-
|
|
103
|
-
// 特殊处理RSS,自动生成url(未来统一维护到 RSS插件里,待下一版主题架构升级)
|
|
104
|
-
const inlineConfig = config.extends as UserConfig<Theme.Config>
|
|
105
|
-
|
|
106
|
-
if (
|
|
107
|
-
inlineConfig.themeConfig?.blog?.RSS
|
|
108
|
-
&& inlineConfig.themeConfig?.blog?.RSS?.icon !== false
|
|
109
|
-
&& inlineConfig.themeConfig?.socialLinks?.length
|
|
110
|
-
&& !inlineConfig.themeConfig?.socialLinks?.[0].link
|
|
111
|
-
) {
|
|
112
|
-
const { RSS } = inlineConfig.themeConfig?.blog
|
|
113
|
-
inlineConfig.themeConfig.socialLinks[0].link = `${RSS.baseUrl}${
|
|
114
|
-
(config.base || '/') + (RSS.filename || 'feed.rss')
|
|
115
|
-
}`
|
|
116
|
-
}
|
|
117
125
|
}
|
package/src/utils/node/theme.ts
CHANGED
|
@@ -126,26 +126,10 @@ export function patchVPConfig(vpConfig: any, cfg?: Partial<Theme.BlogConfig>) {
|
|
|
126
126
|
// TODO: 待确定场景
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
const 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>'
|
|
130
|
-
|
|
131
129
|
export function patchVPThemeConfig(
|
|
132
130
|
cfg?: Partial<Theme.BlogConfig>,
|
|
133
131
|
vpThemeConfig: any = {}
|
|
134
132
|
) {
|
|
135
|
-
// 添加 RSS icon
|
|
136
|
-
const RSS = cfg?.RSS
|
|
137
|
-
if (RSS && RSS.icon !== false) {
|
|
138
|
-
vpThemeConfig.socialLinks = [
|
|
139
|
-
{
|
|
140
|
-
icon: {
|
|
141
|
-
svg: svgIcon
|
|
142
|
-
},
|
|
143
|
-
link: RSS?.url,
|
|
144
|
-
ariaLabel: RSS?.ariaLabel || 'RSS'
|
|
145
|
-
}
|
|
146
|
-
]
|
|
147
|
-
}
|
|
148
|
-
|
|
149
133
|
// 用于自定义sidebar卡片slot
|
|
150
134
|
vpThemeConfig.sidebar = patchDefaultThemeSideBar(cfg)?.sidebar
|
|
151
135
|
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
chineseSearchOptimize,
|
|
7
7
|
pagefindPlugin
|
|
8
8
|
} from 'vitepress-plugin-pagefind'
|
|
9
|
+
import { RssPlugin } from 'vitepress-plugin-rss'
|
|
9
10
|
import type { Theme } from '../../composables/config/index'
|
|
10
|
-
import { genFeed } from './genFeed'
|
|
11
11
|
|
|
12
12
|
export function getVitePlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
13
13
|
const plugins: any[] = []
|
|
@@ -24,6 +24,17 @@ export function getVitePlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
24
24
|
pagefindPlugin({ ...ops, customSearchQuery: chineseSearchOptimize })
|
|
25
25
|
)
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
// 内置支持Mermaid
|
|
29
|
+
if (cfg?.mermaid !== false) {
|
|
30
|
+
const { MermaidPlugin } = require('vitepress-plugin-mermaid')
|
|
31
|
+
plugins.push(MermaidPlugin(cfg?.mermaid === true ? {} : (cfg?.mermaid ?? {})))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 内置支持RSS
|
|
35
|
+
if (cfg?.RSS) {
|
|
36
|
+
plugins.push(RssPlugin(cfg.RSS))
|
|
37
|
+
}
|
|
27
38
|
// 未来移除使用
|
|
28
39
|
// if (cfg && cfg.search !== undefined) {
|
|
29
40
|
// console.log(
|
|
@@ -31,7 +42,6 @@ export function getVitePlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
31
42
|
// )
|
|
32
43
|
// }
|
|
33
44
|
|
|
34
|
-
buildEndFn.push(genFeed)
|
|
35
45
|
return plugins
|
|
36
46
|
}
|
|
37
47
|
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import fs, { writeFileSync } from 'node:fs'
|
|
4
|
-
import { Feed } from 'feed'
|
|
5
|
-
import type { SiteConfig } from 'vitepress'
|
|
6
|
-
import type { Theme } from '../../composables/config/index'
|
|
7
|
-
import { pageMap } from './theme'
|
|
8
|
-
import { withBase } from './index'
|
|
9
|
-
|
|
10
|
-
export async function genFeed(config: SiteConfig) {
|
|
11
|
-
const blogCfg: Theme.BlogConfig = config.userConfig.themeConfig.blog
|
|
12
|
-
let posts: Theme.PageData[] = blogCfg.pagesData
|
|
13
|
-
const { RSS, authorList = [] } = blogCfg
|
|
14
|
-
if (!RSS)
|
|
15
|
-
return
|
|
16
|
-
const { createMarkdownRenderer } = await import('vitepress')
|
|
17
|
-
|
|
18
|
-
const mdRender = await createMarkdownRenderer(
|
|
19
|
-
config.srcDir,
|
|
20
|
-
config.markdown,
|
|
21
|
-
config.site.base,
|
|
22
|
-
config.logger
|
|
23
|
-
)
|
|
24
|
-
console.log()
|
|
25
|
-
console.log('=== feed: https://github.com/jpmonette/feed ===')
|
|
26
|
-
const { base } = config.userConfig
|
|
27
|
-
|
|
28
|
-
const { baseUrl, filename } = RSS
|
|
29
|
-
const feed = new Feed({
|
|
30
|
-
id: baseUrl,
|
|
31
|
-
link: baseUrl,
|
|
32
|
-
...RSS
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
posts.sort(
|
|
36
|
-
(a, b) =>
|
|
37
|
-
+new Date(b.meta.date as string) - +new Date(a.meta.date as string)
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
posts = posts
|
|
41
|
-
// 过滤掉 layout:home
|
|
42
|
-
.filter(v => v.meta.layout !== 'home')
|
|
43
|
-
// 过滤掉不展示的
|
|
44
|
-
.filter(v => v.meta.hidden !== true)
|
|
45
|
-
|
|
46
|
-
if (undefined !== RSS?.limit && RSS?.limit > 0) {
|
|
47
|
-
posts.splice(RSS.limit)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
for (const { route, meta } of posts) {
|
|
51
|
-
const { title, description, date } = meta
|
|
52
|
-
|
|
53
|
-
const author = meta.author ?? blogCfg.author
|
|
54
|
-
let link = `${baseUrl}${withBase(
|
|
55
|
-
base || '',
|
|
56
|
-
// 移除末尾的index
|
|
57
|
-
route.replace(/(^|\/)index$/, '$1')
|
|
58
|
-
)}`
|
|
59
|
-
// 补全后缀
|
|
60
|
-
link = link.endsWith('/')
|
|
61
|
-
? link
|
|
62
|
-
: `${link}${config?.cleanUrls ? '' : '.html'}`
|
|
63
|
-
const authorLink = authorList.find(v => v.nickname === author)?.url
|
|
64
|
-
let html
|
|
65
|
-
const filepath = pageMap.get(route)
|
|
66
|
-
if (filepath) {
|
|
67
|
-
const fileContent = fs.readFileSync(filepath, 'utf-8')
|
|
68
|
-
html = mdRender.render(fileContent)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
feed.addItem({
|
|
72
|
-
title,
|
|
73
|
-
id: link,
|
|
74
|
-
link,
|
|
75
|
-
description,
|
|
76
|
-
content: html,
|
|
77
|
-
author: [
|
|
78
|
-
{
|
|
79
|
-
name: author,
|
|
80
|
-
link: authorLink
|
|
81
|
-
}
|
|
82
|
-
],
|
|
83
|
-
date: new Date(date)
|
|
84
|
-
})
|
|
85
|
-
}
|
|
86
|
-
const RSSFilename = filename || 'feed.rss'
|
|
87
|
-
const RSSFile = path.join(config.outDir, RSSFilename)
|
|
88
|
-
writeFileSync(RSSFile, feed.rss2())
|
|
89
|
-
console.log('🎉 RSS generated', RSSFilename)
|
|
90
|
-
console.log('rss filepath:', RSSFile)
|
|
91
|
-
console.log('rss url:', `${baseUrl}${config.site.base + RSSFilename}`)
|
|
92
|
-
console.log('include', posts.length, 'posts')
|
|
93
|
-
console.log()
|
|
94
|
-
console.log()
|
|
95
|
-
}
|