Files
secrets/crates/secrets-mcp/templates/changelog.html
voson 1b2fbdae4d
Some checks failed
Secrets MCP — Build & Release / 部署 secrets-mcp (push) Has been cancelled
Secrets MCP — Build & Release / 检查 / 构建 / 发版 (push) Has been cancelled
feat(secrets-mcp): /changelog 页(Markdown 渲染)、首页与 Dashboard 入口
- 新增 CHANGELOG.md 构建嵌入、pulldown-cmark 渲染、路由 /changelog
- 首页页脚与 MCP Dashboard 页脚提供变更记录链接;同步 README、AGENTS
- 版本 secrets-mcp 0.5.24
2026-04-11 21:27:26 +08:00

186 lines
7.3 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="canonical" href="{{ base_url }}/changelog">
<link rel="icon" href="/favicon.svg?v={{ version }}" type="image/svg+xml">
<title data-i18n="docTitle">变更记录 — Secrets</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600&family=Inter:wght@400;500;600&display=swap');
:root {
--bg: #0d1117; --surface: #161b22;
--border: #30363d; --text: #e6edf3; --text-muted: #8b949e;
--accent: #58a6ff; --accent-hover: #79b8ff;
}
body { background: var(--bg); color: var(--text); font-family: 'Inter', sans-serif; min-height: 100vh; }
.wrap { max-width: 880px; margin: 0 auto; padding: 24px 20px 48px; }
.top {
display: flex; align-items: center; flex-wrap: wrap; gap: 12px 16px;
margin-bottom: 24px; padding-bottom: 16px;
border-bottom: 1px solid rgba(240,246,252,0.08);
}
.brand {
font-size: 18px; font-weight: 700; color: #fff; text-decoration: none;
}
.brand:hover { color: var(--accent); }
.top-actions { margin-left: auto; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.lang-bar { display: flex; gap: 2px; background: rgba(240,246,252,0.06); border-radius: 8px; padding: 2px; }
.lang-btn { padding: 4px 10px; border: none; background: none; color: #8b949e;
font-size: 12px; cursor: pointer; border-radius: 6px; }
.lang-btn.active { background: rgba(240,246,252,0.1); color: #fff; }
.link-dash {
font-size: 13px; color: var(--accent); text-decoration: none;
}
.link-dash:hover { text-decoration: underline; }
h1 { font-size: 22px; font-weight: 700; margin-bottom: 16px; color: #fff; }
.card {
background: #111827; border: 1px solid rgba(240,246,252,0.08); border-radius: 18px;
padding: 20px 22px;
}
/* Rendered Markdown (pulldown-cmark) */
.changelog-md {
font-size: 14px;
line-height: 1.65;
color: #c9d1d9;
}
.changelog-md > :first-child { margin-top: 0; }
.changelog-md > :last-child { margin-bottom: 0; }
.changelog-md h1 {
font-size: 1.5rem; font-weight: 700; color: #fff;
margin: 1.25em 0 0.5em; padding-bottom: 0.35em;
border-bottom: 1px solid rgba(240,246,252,0.1);
}
.changelog-md h2 {
font-size: 1.2rem; font-weight: 650; color: #f0f6fc;
margin: 1.35em 0 0.5em;
}
.changelog-md h3 { font-size: 1.05rem; font-weight: 600; color: #e6edf3; margin: 1.1em 0 0.45em; }
.changelog-md h4, .changelog-md h5, .changelog-md h6 { font-size: 1rem; font-weight: 600; color: #e6edf3; margin: 1em 0 0.4em; }
.changelog-md p { margin: 0.65em 0; }
.changelog-md ul, .changelog-md ol { margin: 0.65em 0; padding-left: 1.35em; }
.changelog-md li { margin: 0.3em 0; }
.changelog-md li > p { margin: 0.35em 0; }
.changelog-md a { color: var(--accent); text-decoration: none; }
.changelog-md a:hover { text-decoration: underline; }
.changelog-md code {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 0.88em;
background: rgba(240,246,252,0.08);
padding: 0.12em 0.4em;
border-radius: 5px;
}
.changelog-md pre {
margin: 0.85em 0;
padding: 12px 14px;
overflow-x: auto;
background: #0d1117;
border: 1px solid rgba(240,246,252,0.1);
border-radius: 10px;
font-size: 12px;
line-height: 1.5;
}
.changelog-md pre code {
background: none;
padding: 0;
font-size: inherit;
border-radius: 0;
}
.changelog-md blockquote {
margin: 0.75em 0;
padding-left: 1em;
border-left: 3px solid rgba(56,139,253,0.45);
color: var(--text-muted);
}
.changelog-md hr {
margin: 1.25em 0;
border: none;
border-top: 1px solid rgba(240,246,252,0.1);
}
.changelog-md table {
width: 100%;
border-collapse: collapse;
margin: 0.85em 0;
font-size: 13px;
}
.changelog-md th, .changelog-md td {
border: 1px solid var(--border);
padding: 8px 10px;
text-align: left;
}
.changelog-md th { background: rgba(240,246,252,0.06); color: #f0f6fc; }
.changelog-md input[type="checkbox"] { margin-right: 0.35em; vertical-align: middle; }
.foot {
margin-top: 28px; text-align: center; font-size: 11px; color: var(--text-muted);
font-family: 'JetBrains Mono', monospace;
}
.foot a { color: var(--accent); text-decoration: none; }
.foot a:hover { text-decoration: underline; }
</style>
</head>
<body>
<div class="wrap">
<header class="top">
<a href="/" class="brand">secrets</a>
<div class="top-actions">
<a href="/dashboard" class="link-dash" data-i18n="backDash">控制台</a>
<div class="lang-bar" role="group" aria-label="Language">
<button type="button" class="lang-btn" onclick="setLang('zh-CN')"></button>
<button type="button" class="lang-btn" onclick="setLang('zh-TW')"></button>
<button type="button" class="lang-btn" onclick="setLang('en')">EN</button>
</div>
</div>
</header>
<h1 data-i18n="pageTitle">变更记录</h1>
<div class="card changelog-md">
{{ changelog_html|safe }}
</div>
<footer class="foot">
<span data-i18n="versionLabel">版本</span> {{ version }}
</footer>
</div>
<script>
const T = {
'zh-CN': {
docTitle: '变更记录 — Secrets',
pageTitle: '变更记录',
backDash: '控制台',
versionLabel: '版本',
},
'zh-TW': {
docTitle: '變更記錄 — Secrets',
pageTitle: '變更記錄',
backDash: '控制台',
versionLabel: '版本',
},
'en': {
docTitle: 'Changelog — Secrets',
pageTitle: 'Changelog',
backDash: 'Dashboard',
versionLabel: 'Version',
}
};
let currentLang = localStorage.getItem('lang') || 'zh-CN';
function t(key) { return (T[currentLang] && T[currentLang][key]) || T['en'][key] || key; }
function applyLang() {
document.documentElement.lang = currentLang;
document.title = t('docTitle');
document.querySelectorAll('[data-i18n]').forEach(el => {
el.textContent = t(el.getAttribute('data-i18n'));
});
document.querySelectorAll('.lang-btn').forEach(btn => {
const map = { 'zh-CN': '简', 'zh-TW': '繁', 'en': 'EN' };
btn.classList.toggle('active', btn.textContent === map[currentLang]);
});
}
function setLang(lang) {
currentLang = lang;
localStorage.setItem('lang', lang);
applyLang();
}
applyLang();
</script>
</body>
</html>