This commit is contained in:
2025-12-08 01:03:07 +08:00
commit 5c77d25b6d
334 changed files with 71475 additions and 0 deletions

153
scripts/sync-content.js Normal file
View File

@@ -0,0 +1,153 @@
import { execSync } from "child_process";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const rootDir = path.resolve(__dirname, "..");
// 加载 .env 文件
const envPath = path.join(rootDir, ".env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf-8");
envContent.split("\n").forEach((line) => {
line = line.trim();
// 跳过注释和空行
if (!line || line.startsWith("#")) return;
const match = line.match(/^([^=]+)=(.*)$/);
if (match) {
const key = match[1].trim();
let value = match[2].trim();
// 移除引号
value = value.replace(/^["']|["']$/g, "");
process.env[key] = value;
}
});
console.log("Loaded .env configuration file\n");
}
// 从环境变量读取配置
const ENABLE_CONTENT_SYNC = process.env.ENABLE_CONTENT_SYNC !== "false"; // 默认启用
const CONTENT_REPO_URL = process.env.CONTENT_REPO_URL || "";
const CONTENT_DIR = process.env.CONTENT_DIR || path.join(rootDir, "content");
console.log("Starting content synchronization...\n");
// 检查是否启用内容分离
if (!ENABLE_CONTENT_SYNC) {
console.log("Content separation is disabled (ENABLE_CONTENT_SYNC=false)");
console.log(
"Tip: Local content will be used, will not sync from remote repository",
);
console.log(" To enable content separation feature, set in .env:");
console.log(" ENABLE_CONTENT_SYNC=true");
console.log(" CONTENT_REPO_URL=<your-repo-url>\n");
process.exit(0);
}
// 检查内容目录是否存在
if (!fs.existsSync(CONTENT_DIR)) {
console.log(`Content directory does not exist: ${CONTENT_DIR}`);
console.log("Using independent repository mode");
if (!CONTENT_REPO_URL) {
console.warn("Warning: CONTENT_REPO_URL not set, will use local content");
console.log(
"Tip: Please set CONTENT_REPO_URL environment variable or manually create content directory",
);
process.exit(0);
}
try {
console.log(`Cloning content repository: ${CONTENT_REPO_URL}`);
execSync(`git clone --depth 1 ${CONTENT_REPO_URL} ${CONTENT_DIR}`, {
stdio: "inherit",
cwd: rootDir,
});
console.log("Content repository cloned successfully");
} catch (error) {
console.error("Clone failed:", error.message);
process.exit(1);
}
} else {
console.log(`Content directory already exists: ${CONTENT_DIR}`);
if (fs.existsSync(path.join(CONTENT_DIR, ".git"))) {
try {
console.log("Pulling latest content...");
execSync("git pull --allow-unrelated-histories", {
stdio: "inherit",
cwd: CONTENT_DIR,
});
console.log("Content updated successfully");
} catch (error) {
console.warn("Content update failed:", error.message);
}
}
}
// 创建符号链接或复制内容
console.log("\nSetting up content links...");
const contentMappings = [
{ src: "posts", dest: "src/content/posts" },
{ src: "spec", dest: "src/content/spec" },
{ src: "data", dest: "src/data" },
{ src: "images", dest: "public/images" },
];
for (const mapping of contentMappings) {
const srcPath = path.join(CONTENT_DIR, mapping.src);
const destPath = path.join(rootDir, mapping.dest);
if (!fs.existsSync(srcPath)) {
console.log(`Skipping non-existent source: ${mapping.src}`);
continue;
}
// 如果目标已存在且不是符号链接,备份它
if (fs.existsSync(destPath) && !fs.lstatSync(destPath).isSymbolicLink()) {
const backupPath = `${destPath}.backup`;
console.log(
`Backing up existing content: ${mapping.dest} -> ${mapping.dest}.backup`,
);
if (fs.existsSync(backupPath)) {
fs.rmSync(backupPath, { recursive: true, force: true });
}
fs.renameSync(destPath, backupPath);
}
// 删除现有的符号链接
if (fs.existsSync(destPath)) {
fs.unlinkSync(destPath);
}
// 创建符号链接 (Windows 需要管理员权限,否则复制文件)
try {
const relPath = path.relative(path.dirname(destPath), srcPath);
fs.symlinkSync(relPath, destPath, "junction");
console.log(`Created symbolic link: ${mapping.dest} -> ${mapping.src}`);
} catch (error) {
console.log(`Copying content: ${mapping.src} -> ${mapping.dest}`);
copyRecursive(srcPath, destPath);
}
}
console.log("\nContent synchronization completed\n");
// 递归复制函数
function copyRecursive(src, dest) {
if (fs.statSync(src).isDirectory()) {
if (!fs.existsSync(dest)) {
fs.mkdirSync(dest, { recursive: true });
}
const files = fs.readdirSync(src);
for (const file of files) {
copyRecursive(path.join(src, file), path.join(dest, file));
}
} else {
fs.copyFileSync(src, dest);
}
}