Skip to content

Commit 3dba549

Browse files
authored
Merge pull request #66 from devlive-community/dev-archive
发布 2026.0.0
2 parents 59b324c + 4e7190e commit 3dba549

File tree

11 files changed

+164
-46
lines changed

11 files changed

+164
-46
lines changed

docs/content/release/2026.0.0.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
title: 2026.0.0
3+
---
4+
5+
我们很高兴地宣布 PageForge 2026.0.0 正式发布。PageForge 是一款现代化的静态页面生成与部署平台,致力于为用户提供从创建到部署的一站式解决方案。此版本主要增强了阅读体验相关功能。
6+
7+
## 新增功能
8+
9+
- 支持默认 h 标签渲染
10+
- 优化构建速度
11+
- 修复由于未获取 nav + banner 高度导致页面抖动
12+
- 优化修改文件重新编译效率
13+
14+
## 链接
15+
16+
- GitHub: https://github.com/devlive-community/pageforge
17+
- 官网: https://pageforge.devlive.org
18+
19+
## 反馈与支持
20+
21+
如果您在使用过程中遇到任何问题,请通过 GitHub Issues 向我们反馈。您的建议对我们至关重要!
22+
23+
---
24+
25+
此版本重点优化了构建效率,建议所有用户升级到此版本。

docs/pageforge.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ nav:
208208
- Technology:
209209
- /technology/extension
210210
- ReleaseNotes:
211+
- /release/2026.0.0
211212
- /release/2025.1.7
212213
- /release/2025.1.6
213214
- /release/2025.1.5

lib/commands/build.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ class BuildCommand {
99
}
1010

1111
async execute(options = {}) {
12+
const startTime = Date.now();
13+
1214
try {
1315
let config = this.configManager.getConfig();
1416

@@ -40,7 +42,8 @@ class BuildCommand {
4042
const generator = new SiteGenerator(config);
4143
await generator.generate();
4244

43-
console.log('🎉 项目编译完成');
45+
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
46+
console.log(`🎉 项目编译完成,耗时: ${duration}s`);
4447
}
4548
catch (error) {
4649
throw new Error(`Build failed: ${error.message}`);

lib/dev-server.js

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ class DevServer {
1313

1414
async start() {
1515
// 首先构建一次
16+
const startTime = Date.now();
1617
await this.generator.generate();
17-
console.log('🎉 项目编译完成');
18+
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
19+
console.log(`🎉 项目编译完成,耗时: ${duration}s`);
1820

1921
const home = this.config?.version ? this.config.outputPath.replace(this.config.version, '') : this.config.outputPath;
2022
// 设置静态文件服务
@@ -65,19 +67,81 @@ class DevServer {
6567

6668
async handleFileChange(filepath) {
6769
try {
68-
if (filepath.endsWith('pageforge.yaml')) {
69-
console.log('📝 配置文件已更新,重新加载配置并重新编译...');
70-
await this.generator.reloadConfig();
70+
const startTime = Date.now();
71+
72+
// 配置文件或模板文件变化 - 全量编译
73+
if (filepath.endsWith('pageforge.yaml') ||
74+
filepath.includes('/templates/') ||
75+
filepath.includes('\\templates\\')) {
76+
console.log('📝 配置/模板文件已更新,全量重新编译...');
77+
if (filepath.endsWith('pageforge.yaml')) {
78+
await this.generator.reloadConfig();
79+
}
80+
await this.generator.generate();
81+
}
82+
// Markdown 文件变化 - 增量编译
83+
else if (filepath.endsWith('.md')) {
84+
console.log(`📄 Markdown 文件已更新: ${filepath}`);
85+
await this.compileSingleMarkdown(filepath);
86+
}
87+
// 资源文件变化 - 复制资源
88+
else if (this.config.assetsPath && filepath.startsWith(this.config.assetsPath)) {
89+
console.log(`📦 资源文件已更新: ${filepath}`);
90+
await this.generator.copyAssets();
7191
}
92+
// 其他文件 - 全量编译
7293
else {
73-
console.log(`📄 文件 ${filepath} 已更新,正在重新编译...`);
94+
console.log(`📄 文件已更新: ${filepath},全量重新编译...`);
95+
await this.generator.generate();
7496
}
7597

76-
await this.generator.generate();
77-
console.log('✓ 项目重新编译完成');
98+
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
99+
console.log(`✓ 编译完成,耗时: ${duration}s`);
78100
}
79101
catch (error) {
80-
console.error('🤯 项目文件重新编译失败 ', error);
102+
console.error('🤯 编译失败:', error);
103+
}
104+
}
105+
106+
async compileSingleMarkdown(filepath) {
107+
const fs = require('fs');
108+
109+
// 检查文件是否在源目录中
110+
if (!filepath.startsWith(this.config.sourcePath)) {
111+
console.log('文件不在源目录中,跳过编译');
112+
return;
113+
}
114+
115+
// 计算相对路径
116+
const relativePath = path.relative(this.config.sourcePath, filepath);
117+
const sourceDir = path.dirname(filepath);
118+
const filename = path.basename(filepath);
119+
120+
// 判断是否启用国际化
121+
if (this.config.feature?.i18n?.enable) {
122+
// 多语言模式 - 为每个语言编译
123+
const locales = Object.keys(this.config.i18n || {}).filter(key => key !== 'default');
124+
for (const locale of locales) {
125+
const relativeDir = path.relative(this.config.sourcePath, sourceDir);
126+
const baseDir = path.join(locale, relativeDir);
127+
await this.generator.directoryProcessor.fileProcessor.processMarkdownFile(
128+
sourceDir,
129+
baseDir,
130+
filename,
131+
locale,
132+
this.config.sourcePath
133+
);
134+
}
135+
} else {
136+
// 单语言模式
137+
const relativeDir = path.relative(this.config.sourcePath, sourceDir);
138+
await this.generator.directoryProcessor.fileProcessor.processMarkdownFile(
139+
sourceDir,
140+
relativeDir,
141+
filename,
142+
'',
143+
this.config.sourcePath
144+
);
81145
}
82146
}
83147
}

lib/directory-processor.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ class DirectoryProcessor {
183183
// 创建根目录重定向
184184
this.createRootRedirect();
185185

186-
for (const locale of this.getAvailableLocales()) {
186+
// 并发处理多语言
187+
await Promise.all(this.getAvailableLocales().map(async (locale) => {
187188
console.log(`\n📂 处理语言: ${locale.key}`);
188189

189190
// 创建语言目录
@@ -196,7 +197,7 @@ class DirectoryProcessor {
196197
const relativeToSource = path.relative(this.config.sourcePath, sourceDir);
197198
const initialBaseDir = path.join(locale.key, relativeToSource);
198199
await this.processDirectory(sourceDir, initialBaseDir, locale.key, this.config.sourcePath);
199-
}
200+
}));
200201
}
201202
else {
202203
await this.processDirectory(sourceDir, '', '', this.config.sourcePath);
@@ -223,8 +224,8 @@ class DirectoryProcessor {
223224

224225
console.log(`\n📂 处理目录: ${sourceDir}`);
225226

226-
// 处理子目录
227-
for (const file of files) {
227+
// 并发处理子目录
228+
await Promise.all(files.map(async (file) => {
228229
const sourcePath = path.join(sourceDir, file);
229230
const stat = fs.statSync(sourcePath);
230231

@@ -233,11 +234,11 @@ class DirectoryProcessor {
233234
const nextBaseDir = locale ? path.join(locale, relativeToSource) : relativeToSource;
234235
await this.processDirectory(sourcePath, nextBaseDir, locale, rootSourceDir);
235236
}
236-
}
237+
}));
237238

238-
// 处理 Markdown 文件
239+
// 并发处理 Markdown 文件
239240
const markdownFiles = files.filter(file => file.endsWith('.md'));
240-
for (const file of markdownFiles) {
241+
await Promise.all(markdownFiles.map(async (file) => {
241242
const relativeSourceDir = path.relative(rootSourceDir, sourceDir);
242243
const relativeBaseDir = locale ? path.join(locale, relativeSourceDir) : relativeSourceDir;
243244

@@ -248,7 +249,7 @@ class DirectoryProcessor {
248249
locale,
249250
rootSourceDir
250251
);
251-
}
252+
}));
252253

253254
// 处理其他文件
254255
const otherFiles = files.filter(file =>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pageforge",
3-
"version": "2025.1.7",
3+
"version": "2026.0.0",
44
"description": "PageForge 是一款现代化的静态页面生成与部署平台,旨在帮助用户快速创建精美的静态网站,并一键部署到 GitHub Pages。 无论是个人博客、项目文档还是企业官网,PageForge 都能让你轻松实现高效构建、智能部署和即时上线。",
55
"homepage": "https://pageforge.devlive.org",
66
"repository": {

templates/components/header.js

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,9 @@
11
module.exports = function template(item) {
2-
const divClass = () => {
3-
const baseClasses = 'font-bold tracking-tight text-gray-900 dark:text-white my-3 [&_span]:!font-inherit [&_span]:!text-inherit [&_code]:!text-inherit';
4-
5-
switch (item.level) {
6-
case 1:
7-
return `text-3xl sm:text-4xl ${baseClasses} [&_span]:!text-3xl [&_span]:sm:!text-4xl`;
8-
case 2:
9-
return `text-2xl sm:text-3xl ${baseClasses} [&_span]:!text-2xl [&_span]:sm:!text-3xl`;
10-
case 3:
11-
return `text-xl sm:text-2xl ${baseClasses} [&_span]:!text-xl [&_span]:sm:!text-2xl`;
12-
case 4:
13-
return `text-lg sm:text-xl ${baseClasses} [&_span]:!text-lg [&_span]:sm:!text-xl`;
14-
case 5:
15-
return `text-md sm:text-lg ${baseClasses} [&_span]:!text-md [&_span]:sm:!text-lg`;
16-
case 6:
17-
return `text-sm sm:text-md ${baseClasses} [&_span]:!text-sm [&_span]:sm:!text-md`;
18-
default:
19-
return `text-base sm:text-lg ${baseClasses} [&_span]:!text-base [&_span]:sm:!text-lg`;
20-
}
21-
}
2+
const tag = `h${item.level}`;
223

234
return `
24-
<div class="${divClass()}">
25-
<div id="${item.slug}" class="inline-flex items-center">${item.text}</div>
26-
</div>
5+
<${tag} id="${item.slug}">
6+
${item.text}
7+
</${tag}>
278
`;
289
};

templates/components/span.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module.exports = function template(item) {
22
return `
3-
<span class="text-base text-gray-700 leading-7 my-2">${item.text}</span>
3+
<span class="leading-7">${item.text}</span>
44
`;
55
};

templates/includes/header-banner.ejs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<% if (locals.siteData?.banner?.content) { %>
2-
<div class="w-full bg-blue-50 <%= darkClasses('dark:bg-blue-900/20') %>" data-banner>
3-
<div class="max-w-screen-xl px-6 py-3 mx-auto flex items-center justify-between">
2+
<div class="w-full bg-blue-50 <%= darkClasses('dark:bg-blue-900/20') %> h-12" data-banner>
3+
<div class="max-w-screen-xl px-6 mx-auto flex items-center justify-between h-full">
44
<% if (Array.isArray(locals.siteData.banner.content)) { %>
55
<div class="text-blue-700 <%= darkClasses('dark:text-blue-300') %> banner-container">
66
<div class="swiper banner-swiper">

templates/includes/repo.ejs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<% if (locals.siteData.repo) { %>
2-
<div class="hidden lg:flex items-center space-x-4 text-sm" id="github-stats-desktop">
2+
<div class="hidden lg:flex items-center space-x-4 text-sm min-w-[200px]" id="github-stats-desktop">
33
<a href="<%= siteData.repo.url %>"
44
target="_blank"
55
rel="noopener noreferrer"
6-
class="inline-flex items-center gap-3 text-gray-600 hover:text-gray-500 transition-colors">
6+
class="inline-flex items-center gap-3 text-gray-600 hover:text-gray-500 transition-colors min-w-full">
77
<div class="inline-flex items-center">
88
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" class="w-6 h-6">
99
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>

0 commit comments

Comments
 (0)