1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| const express = require('express'); const cors = require('cors'); const { Octokit } = require('@octokit/rest'); require('dotenv').config();
const app = express(); const PORT = process.env.PORT || 3001;
app.use(cors()); app.use(express.json({ limit: '10mb' })); app.use(express.static('../frontend'));
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
app.get('/api/health', (req, res) => { res.json({ status: 'OK', message: 'Markdown Editor API is running' }); });
app.post('/api/save-markdown', async (req, res) => { try { const { content, filename, message, folder = '' } = req.body;
if (!content || !filename) { return res.status(400).json({ success: false, error: '内容和文件名是必需的' }); }
const filePath = folder ? `${folder}/${filename}` : filename;
let sha = null; try { const existingFile = await octokit.repos.getContent({ owner: process.env.GITHUB_OWNER, repo: process.env.GITHUB_REPO, branch: process.env.GITHUB_BRANCH, path: filePath }); sha = existingFile.data.sha; } catch (error) { if (error.status !== 404) { throw error; } }
const response = await octokit.repos.createOrUpdateFileContents({ owner: process.env.GITHUB_OWNER, repo: process.env.GITHUB_REPO, branch: process.env.GITHUB_BRANCH, path: filePath, message: message || `Update ${filename}`, content: Buffer.from(content).toString('base64'), sha: sha, committer: { name: process.env.COMMITTER_NAME || 'Markdown Editor', email: process.env.COMMITTER_EMAIL || 'editor@example.com' } });
res.json({ success: true, message: '文件上传成功', url: response.data.content.html_url, download_url: response.data.content.download_url });
} catch (error) { console.error('Error saving markdown:', error); res.status(500).json({ success: false, error: error.message || '保存文件时发生错误' }); } });
app.get('/api/files', async (req, res) => { try { const { folder = '' } = req.query;
const response = await octokit.repos.getContent({ owner: process.env.GITHUB_OWNER, repo: process.env.GITHUB_REPO, branch: process.env.GITHUB_BRANCH, path: folder });
const files = response.data .filter(item => item.name.endsWith('.md')) .map(item => ({ name: item.name, path: item.path, url: item.html_url, download_url: item.download_url }));
res.json({ success: true, files });
} catch (error) { console.error('Error fetching files:', error); res.status(500).json({ success: false, error: error.message || '获取文件列表时发生错误' }); } });
app.use((error, req, res, next) => { console.error('Unhandled error:', error); res.status(500).json({ success: false, error: '服务器内部错误' }); });
app.listen(PORT, () => { console.log(`🚀 Server running on http://localhost:${PORT}`); console.log(`📝 Markdown Editor API ready`); });
|