@sugarat/theme 0.1.38 → 0.1.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/node.d.ts +42 -8
- package/node.js +292 -206
- package/package.json +4 -3
- package/src/components/BlogArticleAnalyze.vue +2 -2
- package/src/components/BlogFriendLink.vue +2 -2
- package/src/components/BlogHomeOverview.vue +1 -1
- package/src/components/BlogHotArticle.vue +1 -1
- package/src/components/BlogItem.vue +1 -1
- package/src/components/BlogRecommendArticle.vue +19 -9
- package/src/components/BlogSearch.vue +1 -1
- package/src/components/BlogSidebar.vue +22 -6
- package/src/components/UserWorks.vue +1 -1
- package/src/composables/config/index.ts +34 -2
- package/src/node.ts +35 -367
- package/src/styles/index.scss +1 -1
- package/src/utils/{index.ts → client/index.ts} +1 -1
- package/src/utils/node/genFeed.ts +53 -0
- package/src/utils/node/index.ts +118 -0
- package/src/utils/node/mdPlugins.ts +95 -0
- package/src/utils/node/theme.ts +138 -0
- package/src/utils/node/vitePlugins.ts +98 -0
package/README.md
CHANGED
|
@@ -50,4 +50,5 @@ pnpm serve
|
|
|
50
50
|
* [element-plus](https://github.com/element-plus/element-plus)
|
|
51
51
|
* [charles7c.github.io](https://github.com/Charles7c/charles7c.github.io)
|
|
52
52
|
* [vitepress-blog-zaun](https://github.com/clark-cui/vitepress-blog-zaun)
|
|
53
|
-
* [surmon](https://surmon.me/)
|
|
53
|
+
* [surmon](https://surmon.me/)
|
|
54
|
+
* [vuejs/blog](https://github.com/vuejs/blog/tree/main)
|
package/node.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DefaultTheme, UserConfig } from 'vitepress';
|
|
2
2
|
import { ElButton } from 'element-plus';
|
|
3
|
+
import { FeedOptions } from 'feed';
|
|
3
4
|
export { tabsMarkdownPlugin } from 'vitepress-plugin-tabs';
|
|
4
5
|
|
|
5
6
|
declare namespace BlogPopover {
|
|
@@ -101,11 +102,16 @@ declare namespace Theme {
|
|
|
101
102
|
nextText?: string;
|
|
102
103
|
/**
|
|
103
104
|
* 是否展示当前正在浏览的文章在左侧
|
|
104
|
-
* @default
|
|
105
|
+
* @default true
|
|
105
106
|
*/
|
|
106
107
|
showSelf?: boolean;
|
|
107
108
|
filter?: (page: Theme.PageData) => boolean;
|
|
108
109
|
empty?: string | boolean;
|
|
110
|
+
/**
|
|
111
|
+
* 设置推荐文章的展示风格
|
|
112
|
+
* @default 'sidebar'
|
|
113
|
+
*/
|
|
114
|
+
style?: 'card' | 'sidebar';
|
|
109
115
|
}
|
|
110
116
|
interface HomeBlog {
|
|
111
117
|
name?: string;
|
|
@@ -241,10 +247,36 @@ declare namespace Theme {
|
|
|
241
247
|
works?: UserWorks;
|
|
242
248
|
/**
|
|
243
249
|
* https://mermaid.js.org/config/setup/modules/mermaidAPI.html#mermaidapi-configuration-defaults for options
|
|
244
|
-
* @default
|
|
250
|
+
* @default true
|
|
245
251
|
*/
|
|
246
252
|
mermaid?: any;
|
|
253
|
+
/**
|
|
254
|
+
* 设置解析 frontmatter 里 date 的时区
|
|
255
|
+
* @default 8 => 'UTC+8'
|
|
256
|
+
* */
|
|
257
|
+
timeZone?: number;
|
|
258
|
+
/**
|
|
259
|
+
* 启用RSS配置
|
|
260
|
+
*/
|
|
261
|
+
RSS?: RSSOptions;
|
|
247
262
|
}
|
|
263
|
+
type RSSOptions = FeedOptions & {
|
|
264
|
+
baseUrl: string;
|
|
265
|
+
/**
|
|
266
|
+
* 线上访问的RSS地址
|
|
267
|
+
*/
|
|
268
|
+
url: string;
|
|
269
|
+
/**
|
|
270
|
+
* 输出的RSS文件名
|
|
271
|
+
* @default 'feed.rss'
|
|
272
|
+
*/
|
|
273
|
+
filename?: string;
|
|
274
|
+
/**
|
|
275
|
+
* 是否展示RSS的图标
|
|
276
|
+
* @default true
|
|
277
|
+
*/
|
|
278
|
+
showIcon?: boolean;
|
|
279
|
+
};
|
|
248
280
|
interface Config extends DefaultTheme.Config {
|
|
249
281
|
blog?: BlogConfig;
|
|
250
282
|
}
|
|
@@ -257,12 +289,14 @@ declare namespace Theme {
|
|
|
257
289
|
}
|
|
258
290
|
}
|
|
259
291
|
|
|
292
|
+
/**
|
|
293
|
+
* 获取主题的配置
|
|
294
|
+
* @param cfg 主题配置
|
|
295
|
+
*/
|
|
260
296
|
declare function getThemeConfig(cfg?: Partial<Theme.BlogConfig>): any;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
declare function getGitTimestamp(file: string): Promise<unknown>;
|
|
265
|
-
declare function assignMermaid(config: any): void;
|
|
297
|
+
/**
|
|
298
|
+
* defineConfig Helper
|
|
299
|
+
*/
|
|
266
300
|
declare function defineConfig(config: UserConfig<Theme.Config>): any;
|
|
267
301
|
|
|
268
|
-
export {
|
|
302
|
+
export { defineConfig, getThemeConfig };
|
package/node.js
CHANGED
|
@@ -26,23 +26,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
26
26
|
// src/node.ts
|
|
27
27
|
var node_exports = {};
|
|
28
28
|
__export(node_exports, {
|
|
29
|
-
assignMermaid: () => assignMermaid,
|
|
30
|
-
clearMatterContent: () => clearMatterContent,
|
|
31
29
|
defineConfig: () => defineConfig,
|
|
32
|
-
getDefaultTitle: () => getDefaultTitle,
|
|
33
|
-
getFileBirthTime: () => getFileBirthTime,
|
|
34
|
-
getGitTimestamp: () => getGitTimestamp,
|
|
35
30
|
getThemeConfig: () => getThemeConfig,
|
|
36
31
|
tabsMarkdownPlugin: () => tabsPlugin
|
|
37
32
|
});
|
|
38
33
|
module.exports = __toCommonJS(node_exports);
|
|
39
|
-
var import_fast_glob = __toESM(require("fast-glob"));
|
|
40
|
-
var import_gray_matter = __toESM(require("gray-matter"));
|
|
41
|
-
var import_fs = __toESM(require("fs"));
|
|
42
|
-
var import_child_process = require("child_process");
|
|
43
|
-
var import_path = __toESM(require("path"));
|
|
44
34
|
|
|
45
|
-
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.0.0-
|
|
35
|
+
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.0.0-rc.4_vue@3.3.4/node_modules/vitepress-plugin-tabs/dist/index.js
|
|
46
36
|
var tabsMarker = "=tabs";
|
|
47
37
|
var tabsMarkerLen = tabsMarker.length;
|
|
48
38
|
var ruleBlockTabs = (state, startLine, endLine, silent) => {
|
|
@@ -206,7 +196,10 @@ var tabsPlugin = (md) => {
|
|
|
206
196
|
};
|
|
207
197
|
};
|
|
208
198
|
|
|
209
|
-
// src/utils/index.ts
|
|
199
|
+
// src/utils/node/index.ts
|
|
200
|
+
var import_child_process = require("child_process");
|
|
201
|
+
|
|
202
|
+
// src/utils/client/index.ts
|
|
210
203
|
function formatDate(d, fmt = "yyyy-MM-dd hh:mm:ss") {
|
|
211
204
|
if (!(d instanceof Date)) {
|
|
212
205
|
d = new Date(d);
|
|
@@ -236,158 +229,7 @@ function formatDate(d, fmt = "yyyy-MM-dd hh:mm:ss") {
|
|
|
236
229
|
return fmt;
|
|
237
230
|
}
|
|
238
231
|
|
|
239
|
-
// src/node.ts
|
|
240
|
-
var checkKeys = ["themeConfig"];
|
|
241
|
-
function getThemeConfig(cfg) {
|
|
242
|
-
const srcDir = cfg?.srcDir || process.argv.slice(2)?.[1] || ".";
|
|
243
|
-
const files = import_fast_glob.default.sync(`${srcDir}/**/*.md`, { ignore: ["node_modules"] });
|
|
244
|
-
const data = files.map((v) => {
|
|
245
|
-
let route = v.replace(".md", "");
|
|
246
|
-
if (route.startsWith("./")) {
|
|
247
|
-
route = route.replace(
|
|
248
|
-
new RegExp(
|
|
249
|
-
`^\\.\\/${import_path.default.join(srcDir, "/").replace(new RegExp(`\\${import_path.default.sep}`, "g"), "/")}`
|
|
250
|
-
),
|
|
251
|
-
""
|
|
252
|
-
);
|
|
253
|
-
} else {
|
|
254
|
-
route = route.replace(
|
|
255
|
-
new RegExp(
|
|
256
|
-
`^${import_path.default.join(srcDir, "/").replace(new RegExp(`\\${import_path.default.sep}`, "g"), "/")}`
|
|
257
|
-
),
|
|
258
|
-
""
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
const fileContent = import_fs.default.readFileSync(v, "utf-8");
|
|
262
|
-
const meta = {
|
|
263
|
-
...(0, import_gray_matter.default)(fileContent).data
|
|
264
|
-
};
|
|
265
|
-
if (!meta.title) {
|
|
266
|
-
meta.title = getDefaultTitle(fileContent);
|
|
267
|
-
}
|
|
268
|
-
if (!meta.date) {
|
|
269
|
-
meta.date = getFileBirthTime(v);
|
|
270
|
-
} else {
|
|
271
|
-
meta.date = formatDate(
|
|
272
|
-
new Date(`${new Date(meta.date).toUTCString()}+8`)
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
meta.categories = typeof meta.categories === "string" ? [meta.categories] : meta.categories;
|
|
276
|
-
meta.tags = typeof meta.tags === "string" ? [meta.tags] : meta.tags;
|
|
277
|
-
meta.tag = [meta.tag || []].flat().concat([
|
|
278
|
-
.../* @__PURE__ */ new Set([...meta.categories || [], ...meta.tags || []])
|
|
279
|
-
]);
|
|
280
|
-
const wordCount = 100;
|
|
281
|
-
meta.description = meta.description || getTextSummary(fileContent, wordCount);
|
|
282
|
-
meta.cover = meta.cover ?? (fileContent.match(/[!]\[.*?\]\((https:\/\/.+)\)/)?.[1] || "");
|
|
283
|
-
if (meta.publish === false) {
|
|
284
|
-
meta.hidden = true;
|
|
285
|
-
meta.recommend = false;
|
|
286
|
-
}
|
|
287
|
-
return {
|
|
288
|
-
route: `/${route}`,
|
|
289
|
-
meta
|
|
290
|
-
};
|
|
291
|
-
}).filter((v) => v.meta.layout !== "home");
|
|
292
|
-
const extraConfig = {};
|
|
293
|
-
if (cfg?.search === "pagefind" || cfg?.search instanceof Object && cfg.search.mode === "pagefind") {
|
|
294
|
-
checkKeys.push("vite");
|
|
295
|
-
let resolveConfig;
|
|
296
|
-
extraConfig.vite = {
|
|
297
|
-
plugins: [
|
|
298
|
-
{
|
|
299
|
-
name: "@sugarar/theme-plugin-pagefind",
|
|
300
|
-
enforce: "pre",
|
|
301
|
-
configResolved(config) {
|
|
302
|
-
if (resolveConfig) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
resolveConfig = config;
|
|
306
|
-
const vitepressConfig = config.vitepress;
|
|
307
|
-
if (!vitepressConfig) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
const selfBuildEnd = vitepressConfig.buildEnd;
|
|
311
|
-
vitepressConfig.buildEnd = (siteConfig) => {
|
|
312
|
-
selfBuildEnd?.(siteConfig);
|
|
313
|
-
const ignore = [
|
|
314
|
-
"div.aside",
|
|
315
|
-
"a.header-anchor"
|
|
316
|
-
];
|
|
317
|
-
const { log } = console;
|
|
318
|
-
log();
|
|
319
|
-
log("=== pagefind: https://pagefind.app/ ===");
|
|
320
|
-
let command = `npx pagefind --source ${import_path.default.join(
|
|
321
|
-
process.argv.slice(2)?.[1] || ".",
|
|
322
|
-
".vitepress/dist"
|
|
323
|
-
)}`;
|
|
324
|
-
if (ignore.length) {
|
|
325
|
-
command += ` --exclude-selectors "${ignore.join(", ")}"`;
|
|
326
|
-
}
|
|
327
|
-
log(command);
|
|
328
|
-
log();
|
|
329
|
-
(0, import_child_process.execSync)(command, {
|
|
330
|
-
stdio: "inherit"
|
|
331
|
-
});
|
|
332
|
-
};
|
|
333
|
-
},
|
|
334
|
-
transform(code, id) {
|
|
335
|
-
if (id.endsWith("theme-default/Layout.vue")) {
|
|
336
|
-
return code.replace(
|
|
337
|
-
"<VPContent>",
|
|
338
|
-
"<VPContent data-pagefind-body>"
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
return code;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
]
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
const markdownPlugin = [];
|
|
348
|
-
if (cfg?.tabs) {
|
|
349
|
-
markdownPlugin.push(tabsPlugin);
|
|
350
|
-
}
|
|
351
|
-
if (cfg) {
|
|
352
|
-
cfg.mermaid = cfg?.mermaid ?? true;
|
|
353
|
-
}
|
|
354
|
-
if (cfg?.mermaid !== false) {
|
|
355
|
-
const { MermaidMarkdown } = require("vitepress-plugin-mermaid");
|
|
356
|
-
markdownPlugin.push(MermaidMarkdown);
|
|
357
|
-
}
|
|
358
|
-
if (markdownPlugin.length) {
|
|
359
|
-
extraConfig.markdown = {
|
|
360
|
-
config(...rest) {
|
|
361
|
-
markdownPlugin.forEach((plugin) => {
|
|
362
|
-
plugin?.(...rest);
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
return {
|
|
368
|
-
themeConfig: {
|
|
369
|
-
blog: {
|
|
370
|
-
pagesData: data,
|
|
371
|
-
...cfg
|
|
372
|
-
},
|
|
373
|
-
...cfg?.blog !== false && cfg?.recommend !== false ? {
|
|
374
|
-
sidebar: [
|
|
375
|
-
{
|
|
376
|
-
text: "",
|
|
377
|
-
items: []
|
|
378
|
-
}
|
|
379
|
-
]
|
|
380
|
-
} : void 0
|
|
381
|
-
},
|
|
382
|
-
...extraConfig
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
function getDefaultTitle(content) {
|
|
386
|
-
const title = clearMatterContent(content).split("\n")?.find((str) => {
|
|
387
|
-
return str.startsWith("# ");
|
|
388
|
-
})?.slice(2).replace(/^\s+|\s+$/g, "") || "";
|
|
389
|
-
return title;
|
|
390
|
-
}
|
|
232
|
+
// src/utils/node/index.ts
|
|
391
233
|
function clearMatterContent(content) {
|
|
392
234
|
let first___;
|
|
393
235
|
let second___;
|
|
@@ -407,6 +249,12 @@ function clearMatterContent(content) {
|
|
|
407
249
|
}, []);
|
|
408
250
|
return lines.slice(second___ || 0).join("\n");
|
|
409
251
|
}
|
|
252
|
+
function getDefaultTitle(content) {
|
|
253
|
+
const title = clearMatterContent(content).split("\n")?.find((str) => {
|
|
254
|
+
return str.startsWith("# ");
|
|
255
|
+
})?.slice(2).replace(/^\s+|\s+$/g, "") || "";
|
|
256
|
+
return title;
|
|
257
|
+
}
|
|
410
258
|
function getFileBirthTime(url) {
|
|
411
259
|
let date = new Date();
|
|
412
260
|
try {
|
|
@@ -419,24 +267,51 @@ function getFileBirthTime(url) {
|
|
|
419
267
|
}
|
|
420
268
|
return formatDate(date);
|
|
421
269
|
}
|
|
422
|
-
function getGitTimestamp(file) {
|
|
423
|
-
return new Promise((resolve, reject) => {
|
|
424
|
-
const child = (0, import_child_process.spawn)("git", ["log", "-1", '--pretty="%ci"', file]);
|
|
425
|
-
let output = "";
|
|
426
|
-
child.stdout.on("data", (d) => {
|
|
427
|
-
output += String(d);
|
|
428
|
-
});
|
|
429
|
-
child.on("close", () => {
|
|
430
|
-
resolve(+new Date(output));
|
|
431
|
-
});
|
|
432
|
-
child.on("error", reject);
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
270
|
function getTextSummary(text, count = 100) {
|
|
436
271
|
return clearMatterContent(text).match(/^# ([\s\S]+)/m)?.[1]?.replace(/#/g, "")?.replace(/!\[.*?\]\(.*?\)/g, "")?.replace(/\[(.*?)\]\(.*?\)/g, "$1")?.replace(/\*\*(.*?)\*\*/g, "$1")?.split("\n")?.filter((v) => !!v)?.slice(1)?.join("\n")?.replace(/>(.*)/, "")?.slice(0, count);
|
|
437
272
|
}
|
|
273
|
+
function aliasObjectToArray(obj) {
|
|
274
|
+
return Object.entries(obj).map(([find, replacement]) => ({
|
|
275
|
+
find,
|
|
276
|
+
replacement
|
|
277
|
+
}));
|
|
278
|
+
}
|
|
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
|
+
|
|
287
|
+
// src/utils/node/mdPlugins.ts
|
|
288
|
+
function getMarkdownPlugins(cfg) {
|
|
289
|
+
const markdownPlugin = [];
|
|
290
|
+
if (cfg?.tabs) {
|
|
291
|
+
markdownPlugin.push(tabsPlugin);
|
|
292
|
+
}
|
|
293
|
+
if (cfg) {
|
|
294
|
+
cfg.mermaid = cfg?.mermaid ?? true;
|
|
295
|
+
if (cfg?.mermaid !== false) {
|
|
296
|
+
const { MermaidMarkdown } = require("vitepress-plugin-mermaid");
|
|
297
|
+
markdownPlugin.push(MermaidMarkdown);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return markdownPlugin;
|
|
301
|
+
}
|
|
302
|
+
function registerMdPlugins(vpCfg, plugins) {
|
|
303
|
+
if (plugins.length) {
|
|
304
|
+
vpCfg.markdown = {
|
|
305
|
+
config(...rest) {
|
|
306
|
+
plugins.forEach((plugin) => {
|
|
307
|
+
plugin?.(...rest);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
438
313
|
function assignMermaid(config) {
|
|
439
|
-
if (!config
|
|
314
|
+
if (!config?.mermaid)
|
|
440
315
|
return;
|
|
441
316
|
if (!config.vite)
|
|
442
317
|
config.vite = {};
|
|
@@ -457,50 +332,261 @@ function assignMermaid(config) {
|
|
|
457
332
|
{ find: /^dayjs\/(.*).js/, replacement: "dayjs/esm/$1" }
|
|
458
333
|
];
|
|
459
334
|
}
|
|
460
|
-
function
|
|
461
|
-
|
|
462
|
-
find,
|
|
463
|
-
replacement
|
|
464
|
-
}));
|
|
465
|
-
}
|
|
466
|
-
function defineConfig(config) {
|
|
467
|
-
if (config.themeConfig?.themeConfig) {
|
|
468
|
-
config.extends = checkKeys.reduce((pre, key) => {
|
|
469
|
-
pre[key] = config.themeConfig[key];
|
|
470
|
-
delete config.themeConfig[key];
|
|
471
|
-
return pre;
|
|
472
|
-
}, {});
|
|
473
|
-
setTimeout(() => {
|
|
474
|
-
console.warn("==\u2193 \u4E3B\u9898\u914D\u7F6E\u65B9\u5F0F\u8FC7\u671F\uFF0C\u8BF7\u5C3D\u5FEB\u53C2\u7167\u6587\u6863\u66F4\u65B0 \u2193==");
|
|
475
|
-
console.warn("https://theme.sugarat.top/config/global.html");
|
|
476
|
-
}, 1200);
|
|
477
|
-
}
|
|
478
|
-
const extendThemeConfig = config.extends?.themeConfig?.blog;
|
|
335
|
+
function wrapperCfgWithMermaid(config) {
|
|
336
|
+
const extendThemeConfig = config.extends?.themeConfig?.blog || {};
|
|
479
337
|
const resultConfig = extendThemeConfig.mermaid === false ? config : {
|
|
480
338
|
...config,
|
|
481
339
|
mermaid: extendThemeConfig.mermaid === true ? {} : extendThemeConfig.mermaid
|
|
482
340
|
};
|
|
483
341
|
assignMermaid(resultConfig);
|
|
484
|
-
|
|
485
|
-
|
|
342
|
+
return resultConfig;
|
|
343
|
+
}
|
|
344
|
+
function supportRunExtendsPlugin(config) {
|
|
345
|
+
if (!config.markdown)
|
|
346
|
+
config.markdown = {};
|
|
486
347
|
if (config.extends?.markdown?.config) {
|
|
487
348
|
const markdownExtendsConfigOriginal = config.extends?.markdown?.config;
|
|
488
|
-
const selfMarkdownConfig =
|
|
489
|
-
|
|
349
|
+
const selfMarkdownConfig = config.markdown?.config;
|
|
350
|
+
config.markdown.config = (...rest) => {
|
|
490
351
|
selfMarkdownConfig?.(...rest);
|
|
491
352
|
markdownExtendsConfigOriginal?.(...rest);
|
|
492
353
|
};
|
|
493
354
|
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// src/utils/node/theme.ts
|
|
358
|
+
var import_fast_glob = __toESM(require("fast-glob"));
|
|
359
|
+
var import_gray_matter = __toESM(require("gray-matter"));
|
|
360
|
+
var import_fs = __toESM(require("fs"));
|
|
361
|
+
var import_path = __toESM(require("path"));
|
|
362
|
+
function patchDefaultThemeSideBar(cfg) {
|
|
363
|
+
return cfg?.blog !== false && cfg?.recommend !== false ? {
|
|
364
|
+
sidebar: [
|
|
365
|
+
{
|
|
366
|
+
text: "",
|
|
367
|
+
items: []
|
|
368
|
+
}
|
|
369
|
+
]
|
|
370
|
+
} : void 0;
|
|
371
|
+
}
|
|
372
|
+
function getArticles(cfg) {
|
|
373
|
+
const srcDir = cfg?.srcDir || process.argv.slice(2)?.[1] || ".";
|
|
374
|
+
const files = import_fast_glob.default.sync(`${srcDir}/**/*.md`, { ignore: ["node_modules"] });
|
|
375
|
+
const data = files.map((v) => {
|
|
376
|
+
let route = v.replace(".md", "");
|
|
377
|
+
if (route.startsWith("./")) {
|
|
378
|
+
route = route.replace(
|
|
379
|
+
new RegExp(
|
|
380
|
+
`^\\.\\/${import_path.default.join(srcDir, "/").replace(new RegExp(`\\${import_path.default.sep}`, "g"), "/")}`
|
|
381
|
+
),
|
|
382
|
+
""
|
|
383
|
+
);
|
|
384
|
+
} else {
|
|
385
|
+
route = route.replace(
|
|
386
|
+
new RegExp(
|
|
387
|
+
`^${import_path.default.join(srcDir, "/").replace(new RegExp(`\\${import_path.default.sep}`, "g"), "/")}`
|
|
388
|
+
),
|
|
389
|
+
""
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
const fileContent = import_fs.default.readFileSync(v, "utf-8");
|
|
393
|
+
const meta = {
|
|
394
|
+
...(0, import_gray_matter.default)(fileContent).data
|
|
395
|
+
};
|
|
396
|
+
if (!meta.title) {
|
|
397
|
+
meta.title = getDefaultTitle(fileContent);
|
|
398
|
+
}
|
|
399
|
+
if (!meta.date) {
|
|
400
|
+
meta.date = getFileBirthTime(v);
|
|
401
|
+
} else {
|
|
402
|
+
const timeZone = cfg?.timeZone ?? 8;
|
|
403
|
+
meta.date = formatDate(
|
|
404
|
+
new Date(`${new Date(meta.date).toUTCString()}+${timeZone}`)
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
meta.categories = typeof meta.categories === "string" ? [meta.categories] : meta.categories;
|
|
408
|
+
meta.tags = typeof meta.tags === "string" ? [meta.tags] : meta.tags;
|
|
409
|
+
meta.tag = [meta.tag || []].flat().concat([
|
|
410
|
+
.../* @__PURE__ */ new Set([...meta.categories || [], ...meta.tags || []])
|
|
411
|
+
]);
|
|
412
|
+
const wordCount = 100;
|
|
413
|
+
meta.description = meta.description || getTextSummary(fileContent, wordCount);
|
|
414
|
+
meta.cover = meta.cover ?? (fileContent.match(/[!]\[.*?\]\((https:\/\/.+)\)/)?.[1] || "");
|
|
415
|
+
if (meta.publish === false) {
|
|
416
|
+
meta.hidden = true;
|
|
417
|
+
meta.recommend = false;
|
|
418
|
+
}
|
|
419
|
+
return {
|
|
420
|
+
route: `/${route}`,
|
|
421
|
+
meta
|
|
422
|
+
};
|
|
423
|
+
}).filter((v) => v.meta.layout !== "home");
|
|
424
|
+
return data;
|
|
425
|
+
}
|
|
426
|
+
function patchVPThemeConfig(cfg, vpThemeConfig = {}) {
|
|
427
|
+
const RSS = cfg?.RSS;
|
|
428
|
+
if (RSS && RSS.showIcon !== false) {
|
|
429
|
+
vpThemeConfig.socialLinks = [
|
|
430
|
+
{
|
|
431
|
+
icon: {
|
|
432
|
+
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>'
|
|
433
|
+
},
|
|
434
|
+
link: RSS.url
|
|
435
|
+
}
|
|
436
|
+
];
|
|
437
|
+
}
|
|
438
|
+
vpThemeConfig.sidebar = patchDefaultThemeSideBar(cfg)?.sidebar;
|
|
439
|
+
return vpThemeConfig;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// src/utils/node/vitePlugins.ts
|
|
443
|
+
var import_path3 = __toESM(require("path"));
|
|
444
|
+
var import_child_process2 = require("child_process");
|
|
445
|
+
|
|
446
|
+
// src/utils/node/genFeed.ts
|
|
447
|
+
var import_path2 = __toESM(require("path"));
|
|
448
|
+
var import_fs2 = require("fs");
|
|
449
|
+
var import_feed = require("feed");
|
|
450
|
+
function genFeed(config) {
|
|
451
|
+
const blogCfg = config.userConfig.themeConfig.blog;
|
|
452
|
+
const posts = blogCfg.pagesData;
|
|
453
|
+
const { RSS, authorList = [] } = blogCfg;
|
|
454
|
+
if (!RSS)
|
|
455
|
+
return;
|
|
456
|
+
console.log();
|
|
457
|
+
console.log("=== feed: https://github.com/jpmonette/feed ===");
|
|
458
|
+
const { base } = config.userConfig;
|
|
459
|
+
const { baseUrl, filename } = RSS;
|
|
460
|
+
const feed = new import_feed.Feed(RSS);
|
|
461
|
+
posts.sort(
|
|
462
|
+
(a, b) => +new Date(b.meta.date) - +new Date(a.meta.date)
|
|
463
|
+
);
|
|
464
|
+
for (const { route, meta } of posts) {
|
|
465
|
+
const { title, description, date, hidden } = meta;
|
|
466
|
+
if (hidden)
|
|
467
|
+
continue;
|
|
468
|
+
const author = meta.author ?? blogCfg.author;
|
|
469
|
+
const link = `${baseUrl}${withBase(base || "", route)}.html`;
|
|
470
|
+
const authorLink = authorList.find((v) => v.nickname === author)?.url;
|
|
471
|
+
feed.addItem({
|
|
472
|
+
title,
|
|
473
|
+
id: link,
|
|
474
|
+
link,
|
|
475
|
+
description,
|
|
476
|
+
author: [
|
|
477
|
+
{
|
|
478
|
+
name: author,
|
|
479
|
+
link: authorLink
|
|
480
|
+
}
|
|
481
|
+
],
|
|
482
|
+
date: new Date(date)
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
const RSSFile = import_path2.default.join(config.outDir, filename || "feed.rss");
|
|
486
|
+
(0, import_fs2.writeFileSync)(RSSFile, feed.rss2());
|
|
487
|
+
console.log("\u{1F389} RSS generated", filename || "feed.rss");
|
|
488
|
+
console.log();
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// src/utils/node/vitePlugins.ts
|
|
492
|
+
function getVitePlugins(cfg) {
|
|
493
|
+
const plugins = [];
|
|
494
|
+
const buildEndFn = [];
|
|
495
|
+
plugins.push(inlineBuildEndPlugin(buildEndFn));
|
|
496
|
+
if (cfg?.search === "pagefind" || cfg?.search instanceof Object && cfg.search.mode === "pagefind") {
|
|
497
|
+
plugins.push(inlinePagefindPlugin(buildEndFn));
|
|
498
|
+
}
|
|
499
|
+
buildEndFn.push(genFeed);
|
|
500
|
+
return plugins;
|
|
501
|
+
}
|
|
502
|
+
function registerVitePlugins(vpCfg, plugins) {
|
|
503
|
+
vpCfg.vite = {
|
|
504
|
+
plugins
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
function inlinePagefindPlugin(buildEndFn) {
|
|
508
|
+
buildEndFn.push(() => {
|
|
509
|
+
const ignore = [
|
|
510
|
+
"div.aside",
|
|
511
|
+
"a.header-anchor"
|
|
512
|
+
];
|
|
513
|
+
const { log } = console;
|
|
514
|
+
log();
|
|
515
|
+
log("=== pagefind: https://pagefind.app/ ===");
|
|
516
|
+
let command = `npx pagefind --source ${import_path3.default.join(
|
|
517
|
+
process.argv.slice(2)?.[1] || ".",
|
|
518
|
+
".vitepress/dist"
|
|
519
|
+
)}`;
|
|
520
|
+
if (ignore.length) {
|
|
521
|
+
command += ` --exclude-selectors "${ignore.join(", ")}"`;
|
|
522
|
+
}
|
|
523
|
+
log(command);
|
|
524
|
+
log();
|
|
525
|
+
(0, import_child_process2.execSync)(command, {
|
|
526
|
+
stdio: "inherit"
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
return {
|
|
530
|
+
name: "@sugarar/theme-plugin-pagefind",
|
|
531
|
+
enforce: "pre",
|
|
532
|
+
transform(code, id) {
|
|
533
|
+
if (id.endsWith("theme-default/Layout.vue")) {
|
|
534
|
+
return code.replace("<VPContent>", "<VPContent data-pagefind-body>");
|
|
535
|
+
}
|
|
536
|
+
return code;
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
function inlineBuildEndPlugin(buildEndFn) {
|
|
541
|
+
let rewrite = false;
|
|
542
|
+
return {
|
|
543
|
+
name: "@sugarar/theme-plugin-build-end",
|
|
544
|
+
enforce: "pre",
|
|
545
|
+
configResolved(config) {
|
|
546
|
+
if (rewrite) {
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
const vitepressConfig = config.vitepress;
|
|
550
|
+
if (!vitepressConfig) {
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
rewrite = true;
|
|
554
|
+
const selfBuildEnd = vitepressConfig.buildEnd;
|
|
555
|
+
vitepressConfig.buildEnd = (siteCfg) => {
|
|
556
|
+
selfBuildEnd?.(siteCfg);
|
|
557
|
+
buildEndFn.filter((fn) => typeof fn === "function").forEach((fn) => fn(siteCfg));
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// src/node.ts
|
|
564
|
+
function getThemeConfig(cfg) {
|
|
565
|
+
const pagesData = getArticles(cfg);
|
|
566
|
+
const extraVPConfig = {};
|
|
567
|
+
const vitePlugins = getVitePlugins(cfg);
|
|
568
|
+
registerVitePlugins(extraVPConfig, vitePlugins);
|
|
569
|
+
const markdownPlugin = getMarkdownPlugins(cfg);
|
|
570
|
+
registerMdPlugins(extraVPConfig, markdownPlugin);
|
|
571
|
+
return {
|
|
572
|
+
themeConfig: {
|
|
573
|
+
blog: {
|
|
574
|
+
pagesData,
|
|
575
|
+
...cfg
|
|
576
|
+
},
|
|
577
|
+
...patchVPThemeConfig(cfg)
|
|
578
|
+
},
|
|
579
|
+
...extraVPConfig
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
function defineConfig(config) {
|
|
583
|
+
const resultConfig = wrapperCfgWithMermaid(config);
|
|
584
|
+
supportRunExtendsPlugin(resultConfig);
|
|
494
585
|
return resultConfig;
|
|
495
586
|
}
|
|
496
587
|
// Annotate the CommonJS export names for ESM import in node:
|
|
497
588
|
0 && (module.exports = {
|
|
498
|
-
assignMermaid,
|
|
499
|
-
clearMatterContent,
|
|
500
589
|
defineConfig,
|
|
501
|
-
getDefaultTitle,
|
|
502
|
-
getFileBirthTime,
|
|
503
|
-
getGitTimestamp,
|
|
504
590
|
getThemeConfig,
|
|
505
591
|
tabsMarkdownPlugin
|
|
506
592
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sugarat/theme",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.40",
|
|
4
4
|
"description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"exports": {
|
|
@@ -38,6 +38,7 @@
|
|
|
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",
|
|
41
42
|
"gray-matter": "^4.0.3",
|
|
42
43
|
"highlight.js": "^11.7.0",
|
|
43
44
|
"mermaid": "^10.2.4",
|
|
@@ -50,9 +51,9 @@
|
|
|
50
51
|
"sass": "^1.56.1",
|
|
51
52
|
"tsup": " ^6.5.0",
|
|
52
53
|
"typescript": "^4.8.2",
|
|
53
|
-
"vitepress": "1.0.0-
|
|
54
|
+
"vitepress": "1.0.0-rc.4",
|
|
54
55
|
"vitepress-plugin-tabs": "^0.2.0",
|
|
55
|
-
"vue": "^3.
|
|
56
|
+
"vue": "^3.3.4"
|
|
56
57
|
},
|
|
57
58
|
"scripts": {
|
|
58
59
|
"dev": "npm run build:node && npm run dev:docs",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
</span>
|
|
11
11
|
</div>
|
|
12
12
|
<div class="meta-des" ref="$des" id="hack-article-des">
|
|
13
|
-
<!-- TODO
|
|
13
|
+
<!-- TODO:是否需要原创?转载等标签,理论上可以添加标签解决,可以参考 charles7c -->
|
|
14
14
|
<span v-if="author && !hiddenAuthor" class="author">
|
|
15
15
|
<el-icon title="本文作者"><UserFilled /></el-icon>
|
|
16
16
|
<a
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
CollectionTag
|
|
57
57
|
} from '@element-plus/icons-vue'
|
|
58
58
|
import { useBlogConfig, useCurrentArticle } from '../composables/config/blog'
|
|
59
|
-
import countWord, { formatShowDate } from '../utils/
|
|
59
|
+
import countWord, { formatShowDate } from '../utils/client'
|
|
60
60
|
import { Theme } from '../composables/config'
|
|
61
61
|
import BlogDocCover from './BlogDocCover.vue'
|
|
62
62
|
|