diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index ea8d8a0..519a1e1 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -40,11 +40,11 @@ jobs:
- name: Check favicon
run: |
- if [ -f favicon.ico ]; then
+ if [ -f dist/favicon.ico ]; then
echo "Favicon exists"
- ls -l favicon.ico
+ ls -l dist/favicon.ico
else
- echo "Warning: favicon.ico not found"
+ echo "Warning: favicon.ico not found in dist directory"
exit 1
fi
@@ -54,7 +54,7 @@ jobs:
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
- path: '.'
+ path: 'dist'
deploy:
environment:
diff --git a/.gitignore b/.gitignore
index 41e6558..63e6c1e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,29 +1,16 @@
-# 依赖目录
+# 依赖相关
node_modules/
npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-# IDE 配置
+# 构建输出
+dist/
+
+# IDE/编辑器配置
.vscode/
.idea/
-*.sublime-project
-*.sublime-workspace
.specstory
.cursorindexingignore
# 系统文件
.DS_Store
Thumbs.db
-
-# 环境变量
-.env
-.env.local
-.env.*.local
-
-# 日志文件
-*.log
-logs/
-
-# 用户配置文件
-config.user.yml
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 82d21c7..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# 更新日志
-
-本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/) 规范。
-
-## [1.0.0] - 2024-03-20
-
-### 新增
-- 基础导航页面结构
-- 深色主题设计
-- 响应式布局
-- 搜索功能
-- 多页面管理(首页、项目、文章、朋友)
-- 动画效果
-
-### 功能模块
-- 左侧固定导航栏
- - 主导航菜单
- - 社交媒体链接
-- 右侧内容区域
- - 搜索框
- - 分类展示
- - 网站卡片
-
-### 技术实现
-- 使用HTML5语义化标签
-- CSS3现代特性
- - Flexbox布局
- - Grid系统
- - 响应式设计
- - 过渡动画
-- 原生JavaScript实现
- - 页面切换
- - 搜索过滤
- - 动画控制
-
-### 优化
-- 移动端适配
-- 性能优化
-- 代码结构优化
-
-### 文档
-- 添加README.md
-- 添加开发文档
-- 添加贡献指南
-- 添加更新日志
-
-## [0.1.0] - 2025-01-31
-
-### 新增
-- 项目初始化
-- 基础文件结构
-- 开发环境配置
-
-## [1.2.3] - 2024-03-21
-
-### 优化
-- 改进GitHub Pages部署流程
- - 使用官方推荐的部署方式
- - 添加自动化部署配置
- - 优化构建缓存
-- 更新依赖管理
- - 添加开发服务器支持
- - 优化依赖版本控制
-- 改进项目配置
- - 优化.gitignore规则
- - 添加homepage配置
\ No newline at end of file
diff --git a/README.md b/README.md
index 59dd59e..9491e0c 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,23 @@
- Font Awesome 图标
- GitHub Pages / Cloudflare Pages 托管
+## 项目结构
+
+```
+menav/
+├── assets/ # 静态资源文件
+│ ├── style.css # 样式表
+│ └── favicon.ico # 网站图标
+├── src/ # 源代码
+│ ├── generator.js # 静态网站生成器
+│ └── script.js # 前端JavaScript脚本
+├── templates/ # HTML模板
+│ └── index.html # HTML骨架模板文件
+├── dist/ # 生成的静态网站(由generator.js生成)
+├── config.yml # 默认配置文件
+└── config.user.yml # 用户自定义配置文件
+```
+
## 快速开始
1. 克隆仓库
@@ -41,12 +58,14 @@ npm install
```
3. 修改配置
-编辑 `config.yml` 文件,根据你的需求修改网站内容:
-- 修改网站基本信息
-- 添加/修改导航链接
-- 自定义社交媒体链接
-- 更新个人项目展示
-- 添加友情链接等
+- 复制 `config.yml` 为 `config.user.yml`
+- 在 `config.user.yml` 中根据你的需求修改网站内容:
+ - 修改网站基本信息
+ - 添加/修改导航链接
+ - 自定义社交媒体链接
+ - 更新个人项目展示
+ - 添加友情链接等
+
4. 本地预览
```bash
@@ -82,7 +101,7 @@ npm run dev
1. 创建个人配置文件:
- 复制 `config.yml` 为 `config.user.yml`
- 在 `config.user.yml` 中修改配置
- - 这样在后续同步更新时,您的配置不会被覆盖
+ - 提交 `config.user.yml` 到您的仓库,这样GitHub Actions才能使用您的自定义配置进行构建
2. 修改配置信息:
- 修改网站基本信息
@@ -93,7 +112,7 @@ npm run dev
完成以上步骤后,系统会自动部署您的网站。部署完成后,您可以在 Settings -> Pages 中找到您的网站地址。
-> 重要提示: 请务必使用 `config.user.yml` 进行配置,这样在同步上游更新时不会丢失您的个人设置。
+> 重要提示: 请务必使用 `config.user.yml` 进行配置,这样在同步上游更新时不会丢失您的个人设置。同时注意不要在配置文件中包含敏感信息,因为它将被提交到公开仓库。
#### 故障排除
@@ -116,25 +135,29 @@ npm run dev
- 构建输出目录: `/`
- Node.js 版本: `16`或更高
-## 自定义配置
-### 配置文件说明
+### 模板说明
-本项目提供两种配置文件:
-1. `config.yml` - 默认配置模板,会随项目更新
-2. `config.user.yml` - 用户个人配置,不会被项目更新覆盖
+本项目使用模板与配置文件分离的方式生成网站:
-建议使用步骤:
-1. 复制 `config.yml` 为 `config.user.yml`
-2. 在 `config.user.yml` 中进行个性化配置
-3. 原始的 `config.yml` 保持不变
-4. 后续同步更新时,您的个人配置不会被覆盖
+1. `templates/index.html` 是不包含具体内容的HTML骨架模板:
+ - 使用占位符 (如 `{{SITE_TITLE}}`, `{{NAVIGATION}}`, `{{HOME_CONTENT}}`) 标记动态内容的位置
+ - 只包含页面结构、CSS引用和基本Javascript引用
+
+2. 工作原理:
+ - `generator.js` 读取配置文件 (优先使用 `config.user.yml`)
+ - 将配置内容注入到模板中的占位符位置
+ - 生成最终的静态HTML网站
+
+3. 优点:
+ - 清晰分离结构与内容
+ - 用户只需修改配置文件,不需要编辑HTML
+ - 便于更新与维护
-> 注意: `config.user.yml` 已添加到 .gitignore 中,不会被提交到仓库
### 配置文件结构
-`config.yml` 包含以下主要部分:
+`config.user.yml` 应包含以下主要部分:
```yaml
# 网站基本信息
@@ -210,28 +233,28 @@ fonts:
1. 准备图标文件:
- 支持.ico、.png等格式
- 建议尺寸为32x32或16x16像素
- - 将图标文件放在仓库根目录
- - 例如: `favicon.ico` 或 `favicon.png`
+ - 将图标文件放在assets目录下
+ - 例如: `assets/favicon.ico` 或 `assets/favicon.png`
2. 配置图标:
- 在`config.yml`或`config.user.yml`的site部分设置favicon
- 使用相对于仓库根目录的路径
- - 例如: `favicon: favicon.ico`
+ - 例如: `favicon: favicon.ico`(generator会自动从assets目录查找)
- 也可以使用在线图标URL
3. 生成和部署:
- - 运行 `npm run generate` 时会自动复制图标文件
- - 确保图标文件存在于指定位置
+ - 运行 `npm run generate` 时会自动复制图标文件到dist目录
+ - 确保图标文件存在于assets目录中
- 部署后图标会自动显示在浏览器标签页
> 提示: 如果图标没有显示,请检查:
-> 1. 图标文件是否存在于正确位置
+> 1. 图标文件是否存在于assets目录
> 2. 配置文件中的路径是否正确
> 3. 是否重新运行了生成命令
### 添加新的网站链接
-在 `config.yml` 中相应的分类下添加新站点:
+在 `config.user.yml` 中相应的分类下添加新站点:
```yaml
categories:
@@ -244,11 +267,6 @@ categories:
description: 网站描述
```
-## 版本
-
-当前版本: v1.2.3
-
-查看 [CHANGELOG.md](./CHANGELOG.md) 了解详细的更新历史。
## 贡献
diff --git a/favicon.ico b/assets/favicon.ico
similarity index 100%
rename from favicon.ico
rename to assets/favicon.ico
diff --git a/style.css b/assets/style.css
similarity index 100%
rename from style.css
rename to assets/style.css
diff --git a/config.yml b/config.yml
index 05d8f21..4cec57d 100644
--- a/config.yml
+++ b/config.yml
@@ -4,6 +4,7 @@ site:
description: 个人网络导航站
author: Your Name
favicon: favicon.ico # 网站图标,支持ico、png等格式
+ logo_text: 导航站 # 左侧导航栏Logo文字
# 字体设置
fonts:
@@ -62,6 +63,10 @@ categories:
- name: 常用网站
icon: fas fa-star
sites:
+ - name: Linux.do
+ url: https://linux.do/
+ icon: fab fa-linux
+ description: 新的理想型社区
- name: Google
url: https://www.google.com
icon: fab fa-google
diff --git a/CONTRIBUTING.md b/docs/CONTRIBUTING.md
similarity index 100%
rename from CONTRIBUTING.md
rename to docs/CONTRIBUTING.md
diff --git a/DEVELOPMENT.md b/docs/DEVELOPMENT.md
similarity index 100%
rename from DEVELOPMENT.md
rename to docs/DEVELOPMENT.md
diff --git a/index.html b/index.html
deleted file mode 100644
index 515b712..0000000
--- a/index.html
+++ /dev/null
@@ -1,678 +0,0 @@
-
-
-
-
-
- 我的导航
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Hello,
-
Welcome to My Navigation
-
导航菜单
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
我的项目
-
这里展示了我的一些个人项目和开源贡献
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/package.json b/package.json
index 5915744..c603e7b 100644
--- a/package.json
+++ b/package.json
@@ -2,12 +2,14 @@
"name": "menav",
"version": "1.2.3",
"description": "A personal navigation website",
- "main": "generator.js",
+ "main": "src/generator.js",
"homepage": "https://rbetree.github.io/menav",
"scripts": {
- "generate": "node generator.js",
- "dev": "node generator.js && serve .",
- "clean": "rm -rf index.html"
+ "generate": "node src/generator.js",
+ "dev": "node src/generator.js && serve dist",
+ "clean": "rm -rf dist",
+ "build": "npm run clean && npm run generate",
+ "restructure": "node restructure.js"
},
"keywords": [
"navigation",
@@ -29,4 +31,4 @@
"devDependencies": {
"serve": "^14.2.1"
}
-}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/generator.js b/src/generator.js
similarity index 73%
rename from generator.js
rename to src/generator.js
index 8743ea5..996c317 100644
--- a/generator.js
+++ b/src/generator.js
@@ -108,6 +108,17 @@ function generateSocialLinks(social) {
`).join('\n');
}
+// 生成欢迎区域和首页内容
+function generateHomeContent(config) {
+ return `
+
+
${escapeHtml(config.profile.title)}
+
${escapeHtml(config.profile.subtitle)}
+
${escapeHtml(config.profile.description)}
+
+${generateCategories(config.categories)}`;
+}
+
// 生成页面内容
function generatePageContent(pageId, data) {
return `
@@ -286,12 +297,36 @@ ${generateSearchResultsPage(config)}
// 复制静态文件
function copyStaticFiles(config) {
+ // 确保dist目录存在
+ if (!fs.existsSync('dist')) {
+ fs.mkdirSync('dist', { recursive: true });
+ }
+
+ // 复制CSS文件
+ try {
+ fs.copyFileSync('assets/style.css', 'dist/style.css');
+ console.log('Copied style.css to dist/');
+ } catch (e) {
+ console.error('Error copying style.css:', e);
+ }
+
+ // 复制JavaScript文件
+ try {
+ fs.copyFileSync('src/script.js', 'dist/script.js');
+ console.log('Copied script.js to dist/');
+ } catch (e) {
+ console.error('Error copying script.js:', e);
+ }
+
// 如果配置了favicon,确保文件存在并复制
if (config.site.favicon) {
try {
- if (fs.existsSync(config.site.favicon)) {
- fs.copyFileSync(config.site.favicon, path.basename(config.site.favicon));
- console.log(`Copied favicon: ${config.site.favicon}`);
+ if (fs.existsSync(`assets/${config.site.favicon}`)) {
+ fs.copyFileSync(`assets/${config.site.favicon}`, `dist/${path.basename(config.site.favicon)}`);
+ console.log(`Copied favicon: ${config.site.favicon} to dist/`);
+ } else if (fs.existsSync(config.site.favicon)) {
+ fs.copyFileSync(config.site.favicon, `dist/${path.basename(config.site.favicon)}`);
+ console.log(`Copied favicon: ${config.site.favicon} to dist/`);
} else {
console.warn(`Warning: Favicon file not found: ${config.site.favicon}`);
}
@@ -301,15 +336,65 @@ function copyStaticFiles(config) {
}
}
+// 处理模板文件,替换占位符
+function processTemplate(template, config) {
+ const currentYear = new Date().getFullYear();
+ const googleFontsLink = generateGoogleFontsLink(config);
+ const fontVariables = generateFontVariables(config);
+
+ // 创建替换映射
+ const replacements = {
+ '{{SITE_TITLE}}': escapeHtml(config.site.title),
+ '{{SITE_LOGO_TEXT}}': escapeHtml(config.site.logo_text || '导航站'), // 从配置中获取,如果不存在则使用默认值
+ '{{GOOGLE_FONTS}}': googleFontsLink,
+ '{{{FONT_VARIABLES}}}': fontVariables,
+ '{{NAVIGATION}}': generateNavigation(config.navigation),
+ '{{SOCIAL_LINKS}}': generateSocialLinks(config.social),
+ '{{CURRENT_YEAR}}': currentYear,
+ '{{HOME_CONTENT}}': generateHomeContent(config),
+ '{{PROJECTS_CONTENT}}': generatePageContent('projects', config.projects),
+ '{{ARTICLES_CONTENT}}': generatePageContent('articles', config.articles),
+ '{{FRIENDS_CONTENT}}': generatePageContent('friends', config.friends),
+ '{{SEARCH_RESULTS}}': generateSearchResultsPage(config)
+ };
+
+ // 执行替换
+ let processedTemplate = template;
+ for (const [placeholder, value] of Object.entries(replacements)) {
+ processedTemplate = processedTemplate.replace(placeholder, value);
+ }
+
+ return processedTemplate;
+}
+
// 主函数
function main() {
const config = loadConfig();
- const html = generateHTML(config);
try {
+ // 确保dist目录存在
+ if (!fs.existsSync('dist')) {
+ fs.mkdirSync('dist', { recursive: true });
+ }
+
+ // 读取模板文件
+ const templatePath = 'templates/index.html';
+ let htmlContent = '';
+
+ if (fs.existsSync(templatePath)) {
+ // 读取模板并处理
+ const template = fs.readFileSync(templatePath, 'utf8');
+ htmlContent = processTemplate(template, config);
+ console.log(`Using template from ${templatePath} and injecting content`);
+ } else {
+ // 如果没有模板文件,使用生成的HTML
+ htmlContent = generateHTML(config);
+ console.log('No template file found, using generated HTML');
+ }
+
// 生成HTML
- fs.writeFileSync('index.html', html);
- console.log('Successfully generated index.html');
+ fs.writeFileSync('dist/index.html', htmlContent);
+ console.log('Successfully generated dist/index.html');
// 复制静态文件
copyStaticFiles(config);
diff --git a/script.js b/src/script.js
similarity index 100%
rename from script.js
rename to src/script.js
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000..a9bb2d0
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+ {{SITE_TITLE}}
+
+
+ {{GOOGLE_FONTS}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{HOME_CONTENT}}
+
+
+
+
+ {{PROJECTS_CONTENT}}
+
+
+
+
+ {{ARTICLES_CONTENT}}
+
+
+
+
+ {{FRIENDS_CONTENT}}
+
+
+ {{SEARCH_RESULTS}}
+
+
+
+
+
\ No newline at end of file