@sugarat/theme 0.2.11 → 0.2.13
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.js +66 -5
- package/package.json +2 -1
- package/src/components/BlogItem.vue +1 -1
- package/src/utils/node/index.ts +31 -0
- package/src/utils/node/theme.ts +2 -2
- package/src/utils/node/vitePlugins.ts +47 -1
package/node.js
CHANGED
|
@@ -202,6 +202,7 @@ var tabsPlugin = (md) => {
|
|
|
202
202
|
|
|
203
203
|
// src/utils/node/index.ts
|
|
204
204
|
var import_node_child_process = require("child_process");
|
|
205
|
+
var import_node_path = __toESM(require("path"));
|
|
205
206
|
|
|
206
207
|
// src/utils/client/index.ts
|
|
207
208
|
function formatDate(d, fmt = "yyyy-MM-dd hh:mm:ss") {
|
|
@@ -287,6 +288,27 @@ function aliasObjectToArray(obj) {
|
|
|
287
288
|
replacement
|
|
288
289
|
}));
|
|
289
290
|
}
|
|
291
|
+
function joinPath(base, path4) {
|
|
292
|
+
return `${base}${path4}`.replace(/\/+/g, "/");
|
|
293
|
+
}
|
|
294
|
+
function isBase64ImageURL(url) {
|
|
295
|
+
const regex = /^data:image\/[a-z]+;base64,/;
|
|
296
|
+
return regex.test(url);
|
|
297
|
+
}
|
|
298
|
+
function getFirstImagURLFromMD(content, route) {
|
|
299
|
+
const url = content.match(/!\[.*\]\((.*)\)/)?.[1]?.replace(/['"]/g, "");
|
|
300
|
+
const isHTTPSource = url && url.startsWith("http");
|
|
301
|
+
if (!url) {
|
|
302
|
+
return "";
|
|
303
|
+
}
|
|
304
|
+
if (isHTTPSource || isBase64ImageURL(url)) {
|
|
305
|
+
return url;
|
|
306
|
+
}
|
|
307
|
+
const paths = joinPath("/", route).split("/");
|
|
308
|
+
paths.splice(paths.length - 1, 1);
|
|
309
|
+
const relativePath = url.startsWith("/") ? url : import_node_path.default.join(paths.join("/") || "", url);
|
|
310
|
+
return joinPath("/", relativePath);
|
|
311
|
+
}
|
|
290
312
|
|
|
291
313
|
// src/utils/node/mdPlugins.ts
|
|
292
314
|
function getMarkdownPlugins(cfg) {
|
|
@@ -338,7 +360,7 @@ function patchOptimizeDeps(config) {
|
|
|
338
360
|
|
|
339
361
|
// src/utils/node/theme.ts
|
|
340
362
|
var import_node_fs = __toESM(require("fs"));
|
|
341
|
-
var
|
|
363
|
+
var import_node_path2 = __toESM(require("path"));
|
|
342
364
|
var import_node_process = __toESM(require("process"));
|
|
343
365
|
var import_fast_glob = __toESM(require("fast-glob"));
|
|
344
366
|
var import_gray_matter = __toESM(require("gray-matter"));
|
|
@@ -361,14 +383,14 @@ function getArticles(cfg) {
|
|
|
361
383
|
if (route.startsWith("./")) {
|
|
362
384
|
route = route.replace(
|
|
363
385
|
new RegExp(
|
|
364
|
-
`^\\.\\/${
|
|
386
|
+
`^\\.\\/${import_node_path2.default.join(srcDir, "/").replace(new RegExp(`\\${import_node_path2.default.sep}`, "g"), "/")}`
|
|
365
387
|
),
|
|
366
388
|
""
|
|
367
389
|
);
|
|
368
390
|
} else {
|
|
369
391
|
route = route.replace(
|
|
370
392
|
new RegExp(
|
|
371
|
-
`^${
|
|
393
|
+
`^${import_node_path2.default.join(srcDir, "/").replace(new RegExp(`\\${import_node_path2.default.sep}`, "g"), "/")}`
|
|
372
394
|
),
|
|
373
395
|
""
|
|
374
396
|
);
|
|
@@ -399,7 +421,7 @@ function getArticles(cfg) {
|
|
|
399
421
|
]);
|
|
400
422
|
const wordCount = 100;
|
|
401
423
|
meta.description = meta.description || getTextSummary(fileContent, wordCount);
|
|
402
|
-
meta.cover = meta.cover ?? (fileContent
|
|
424
|
+
meta.cover = meta.cover ?? getFirstImagURLFromMD(fileContent, `/${route}`);
|
|
403
425
|
if (meta.publish === false) {
|
|
404
426
|
meta.hidden = true;
|
|
405
427
|
meta.recommend = false;
|
|
@@ -417,15 +439,18 @@ function patchVPThemeConfig(cfg, vpThemeConfig = {}) {
|
|
|
417
439
|
}
|
|
418
440
|
|
|
419
441
|
// src/utils/node/vitePlugins.ts
|
|
420
|
-
var
|
|
442
|
+
var import_node_path3 = __toESM(require("path"));
|
|
421
443
|
var import_node_child_process2 = require("child_process");
|
|
422
444
|
var import_node_process2 = __toESM(require("process"));
|
|
445
|
+
var import_node_fs2 = require("fs");
|
|
446
|
+
var import_node_buffer = require("buffer");
|
|
423
447
|
var import_vitepress_plugin_pagefind = require("vitepress-plugin-pagefind");
|
|
424
448
|
var import_vitepress_plugin_rss = require("vitepress-plugin-rss");
|
|
425
449
|
function getVitePlugins(cfg) {
|
|
426
450
|
const plugins = [];
|
|
427
451
|
const buildEndFn = [];
|
|
428
452
|
plugins.push(inlineBuildEndPlugin(buildEndFn));
|
|
453
|
+
plugins.push(coverImgTransform());
|
|
429
454
|
if (cfg && cfg.search !== false) {
|
|
430
455
|
const ops = cfg.search instanceof Object ? cfg.search : {};
|
|
431
456
|
plugins.push(
|
|
@@ -468,6 +493,42 @@ function inlineBuildEndPlugin(buildEndFn) {
|
|
|
468
493
|
}
|
|
469
494
|
};
|
|
470
495
|
}
|
|
496
|
+
function coverImgTransform() {
|
|
497
|
+
let blogConfig;
|
|
498
|
+
let vitepressConfig;
|
|
499
|
+
let assetsDir;
|
|
500
|
+
return {
|
|
501
|
+
name: "@sugarat/theme-plugin-cover-transform",
|
|
502
|
+
apply: "build",
|
|
503
|
+
enforce: "pre",
|
|
504
|
+
configResolved(config) {
|
|
505
|
+
vitepressConfig = config.vitepress;
|
|
506
|
+
assetsDir = vitepressConfig.assetsDir;
|
|
507
|
+
blogConfig = config.vitepress.site.themeConfig.blog;
|
|
508
|
+
},
|
|
509
|
+
async generateBundle(_, bundle) {
|
|
510
|
+
const assetsMap = Object.entries(bundle).filter(([key]) => {
|
|
511
|
+
return key.startsWith(assetsDir);
|
|
512
|
+
}).map(([_2, value]) => {
|
|
513
|
+
return value;
|
|
514
|
+
});
|
|
515
|
+
for (const page of blogConfig.pagesData) {
|
|
516
|
+
const { cover } = page.meta;
|
|
517
|
+
if (!cover?.startsWith("/")) {
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
try {
|
|
521
|
+
const realPath = import_node_path3.default.join(vitepressConfig.root, cover);
|
|
522
|
+
const fileBuffer = (0, import_node_fs2.readFileSync)(realPath);
|
|
523
|
+
const matchAsset = assetsMap.find((v) => import_node_buffer.Buffer.compare(fileBuffer, v.source));
|
|
524
|
+
page.meta.cover = joinPath("/", matchAsset.fileName);
|
|
525
|
+
} catch (e) {
|
|
526
|
+
vitepressConfig.logger.warn(e?.message);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
}
|
|
471
532
|
|
|
472
533
|
// src/node.ts
|
|
473
534
|
function getThemeConfig(cfg) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sugarat/theme",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.13",
|
|
4
4
|
"description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
|
|
5
5
|
"author": "sugar",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"@documate/vue": "^0.3.1",
|
|
52
52
|
"@element-plus/icons-vue": "^2.1.0",
|
|
53
53
|
"element-plus": "^2.3.4",
|
|
54
|
+
"javascript-stringify": "^2.1.0",
|
|
54
55
|
"pagefind": "1.0.3",
|
|
55
56
|
"sass": "^1.56.1",
|
|
56
57
|
"typescript": "^4.8.2",
|
package/src/utils/node/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable global-require */
|
|
2
2
|
/* eslint-disable prefer-rest-params */
|
|
3
3
|
import { spawn, spawnSync } from 'node:child_process'
|
|
4
|
+
import path from 'node:path'
|
|
4
5
|
import { formatDate } from '../client'
|
|
5
6
|
|
|
6
7
|
export function clearMatterContent(content: string) {
|
|
@@ -118,3 +119,33 @@ export function withBase(base: string, path: string) {
|
|
|
118
119
|
? path
|
|
119
120
|
: joinPath(base, path)
|
|
120
121
|
}
|
|
122
|
+
|
|
123
|
+
function isBase64ImageURL(url: string) {
|
|
124
|
+
// Base64 图片链接的格式为 data:image/[image format];base64,[Base64 编码的数据]
|
|
125
|
+
const regex = /^data:image\/[a-z]+;base64,/
|
|
126
|
+
return regex.test(url)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 从文档内容中提取封面
|
|
131
|
+
* @param content 文档内容
|
|
132
|
+
*/
|
|
133
|
+
export function getFirstImagURLFromMD(content: string, route: string) {
|
|
134
|
+
const url = content.match(/!\[.*\]\((.*)\)/)?.[1]?.replace(/['"]/g, '')
|
|
135
|
+
const isHTTPSource = url && url.startsWith('http')
|
|
136
|
+
if (!url) {
|
|
137
|
+
return ''
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (isHTTPSource || isBase64ImageURL(url)) {
|
|
141
|
+
return url
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// TODO: 其它协议,待补充
|
|
145
|
+
|
|
146
|
+
const paths = joinPath('/', route).split('/')
|
|
147
|
+
paths.splice(paths.length - 1, 1)
|
|
148
|
+
const relativePath = url.startsWith('/') ? url : path.join(paths.join('/') || '', url)
|
|
149
|
+
|
|
150
|
+
return joinPath('/', relativePath)
|
|
151
|
+
}
|
package/src/utils/node/theme.ts
CHANGED
|
@@ -6,7 +6,7 @@ import glob from 'fast-glob'
|
|
|
6
6
|
import matter from 'gray-matter'
|
|
7
7
|
import type { Theme } from '../../composables/config/index'
|
|
8
8
|
import { formatDate } from '../client'
|
|
9
|
-
import { getDefaultTitle, getFileBirthTime, getTextSummary } from './index'
|
|
9
|
+
import { getDefaultTitle, getFileBirthTime, getFirstImagURLFromMD, getTextSummary } from './index'
|
|
10
10
|
|
|
11
11
|
export function patchDefaultThemeSideBar(cfg?: Partial<Theme.BlogConfig>) {
|
|
12
12
|
return cfg?.blog !== false && cfg?.recommend !== false
|
|
@@ -105,7 +105,7 @@ export function getArticles(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
105
105
|
// 获取封面图
|
|
106
106
|
meta.cover
|
|
107
107
|
= meta.cover
|
|
108
|
-
?? (fileContent
|
|
108
|
+
?? (getFirstImagURLFromMD(fileContent, `/${route}`))
|
|
109
109
|
|
|
110
110
|
// 是否发布 默认发布
|
|
111
111
|
if (meta.publish === false) {
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import { execSync } from 'node:child_process'
|
|
3
3
|
import process from 'node:process'
|
|
4
|
+
import { readFileSync } from 'node:fs'
|
|
5
|
+
import { Buffer } from 'node:buffer'
|
|
4
6
|
import type { SiteConfig } from 'vitepress'
|
|
7
|
+
|
|
5
8
|
import {
|
|
6
9
|
chineseSearchOptimize,
|
|
7
10
|
pagefindPlugin
|
|
8
11
|
} from 'vitepress-plugin-pagefind'
|
|
9
12
|
import { RssPlugin } from 'vitepress-plugin-rss'
|
|
10
13
|
import type { Theme } from '../../composables/config/index'
|
|
14
|
+
import { joinPath } from './index'
|
|
11
15
|
|
|
12
16
|
export function getVitePlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
13
17
|
const plugins: any[] = []
|
|
@@ -16,7 +20,8 @@ export function getVitePlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
16
20
|
const buildEndFn: any[] = []
|
|
17
21
|
// 执行自定义的 buildEnd 钩子
|
|
18
22
|
plugins.push(inlineBuildEndPlugin(buildEndFn))
|
|
19
|
-
|
|
23
|
+
// 处理cover image的路径(暂只支持自动识别的文章首图)
|
|
24
|
+
plugins.push(coverImgTransform())
|
|
20
25
|
// 内置简化版的pagefind
|
|
21
26
|
if (cfg && cfg.search !== false) {
|
|
22
27
|
const ops = cfg.search instanceof Object ? cfg.search : {}
|
|
@@ -118,3 +123,44 @@ export function inlineBuildEndPlugin(buildEndFn: any[]) {
|
|
|
118
123
|
}
|
|
119
124
|
}
|
|
120
125
|
}
|
|
126
|
+
|
|
127
|
+
// TODO: 支持frontmatter中的相对路径图片自动处理
|
|
128
|
+
export function coverImgTransform() {
|
|
129
|
+
let blogConfig: Theme.BlogConfig
|
|
130
|
+
let vitepressConfig: SiteConfig
|
|
131
|
+
let assetsDir: string
|
|
132
|
+
return {
|
|
133
|
+
name: '@sugarat/theme-plugin-cover-transform',
|
|
134
|
+
apply: 'build',
|
|
135
|
+
enforce: 'pre',
|
|
136
|
+
configResolved(config: any) {
|
|
137
|
+
vitepressConfig = config.vitepress
|
|
138
|
+
assetsDir = vitepressConfig.assetsDir
|
|
139
|
+
blogConfig = config.vitepress.site.themeConfig.blog
|
|
140
|
+
},
|
|
141
|
+
async generateBundle(_: any, bundle: Record<string, any>) {
|
|
142
|
+
const assetsMap = Object.entries(bundle).filter(([key]) => {
|
|
143
|
+
return key.startsWith(assetsDir)
|
|
144
|
+
}).map(([_, value]) => {
|
|
145
|
+
return value
|
|
146
|
+
})
|
|
147
|
+
for (const page of blogConfig.pagesData) {
|
|
148
|
+
const { cover } = page.meta
|
|
149
|
+
// 是否相对路径引用
|
|
150
|
+
if (!cover?.startsWith('/')) {
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
// 寻找构建后的
|
|
155
|
+
const realPath = path.join(vitepressConfig.root, cover)
|
|
156
|
+
const fileBuffer = readFileSync(realPath)
|
|
157
|
+
const matchAsset = assetsMap.find(v => Buffer.compare(fileBuffer, v.source))
|
|
158
|
+
page.meta.cover = joinPath('/', matchAsset.fileName)
|
|
159
|
+
}
|
|
160
|
+
catch (e: any) {
|
|
161
|
+
vitepressConfig.logger.warn(e?.message)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|