feat(secrets-mcp): /changelog 页(Markdown 渲染)、首页与 Dashboard 入口
- 新增 CHANGELOG.md 构建嵌入、pulldown-cmark 渲染、路由 /changelog - 首页页脚与 MCP Dashboard 页脚提供变更记录链接;同步 README、AGENTS - 版本 secrets-mcp 0.5.24
This commit is contained in:
185
crates/secrets-mcp/templates/changelog.html
Normal file
185
crates/secrets-mcp/templates/changelog.html
Normal file
@@ -0,0 +1,185 @@
|
||||
<!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>
|
||||
@@ -57,6 +57,8 @@
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
margin-top: auto;
|
||||
}
|
||||
.app-footer a { color: var(--accent); text-decoration: none; }
|
||||
.app-footer a:hover { text-decoration: underline; }
|
||||
.card { background: #111827; border: 1px solid rgba(240,246,252,0.08); border-radius: 18px;
|
||||
padding: 20px; width: 100%; }
|
||||
.card-title { font-size: 22px; font-weight: 700; margin-bottom: 24px; color: #fff; }
|
||||
@@ -288,7 +290,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="app-footer">{{ version }}</footer>
|
||||
<footer class="app-footer">{{ version }} · <a href="/changelog" data-i18n="changelogLink">变更记录</a></footer>
|
||||
</div><!-- /main -->
|
||||
</div><!-- /content-shell -->
|
||||
</div><!-- /layout -->
|
||||
@@ -379,6 +381,7 @@ const T = {
|
||||
regenFailed: '重置失败,请刷新页面重试。',
|
||||
ariaShowPw: '显示密码',
|
||||
ariaHidePw: '隐藏密码',
|
||||
changelogLink: '变更记录',
|
||||
},
|
||||
'zh-TW': {
|
||||
navMcp: 'MCP', navEntries: '條目', navTrash: '回收站', navAudit: '審計',
|
||||
@@ -417,6 +420,7 @@ const T = {
|
||||
regenFailed: '重置失敗,請重新整理頁面再試。',
|
||||
ariaShowPw: '顯示密碼',
|
||||
ariaHidePw: '隱藏密碼',
|
||||
changelogLink: '變更記錄',
|
||||
},
|
||||
'en': {
|
||||
navMcp: 'MCP', navEntries: 'Entries', navTrash: 'Trash', navAudit: 'Audit',
|
||||
@@ -455,6 +459,7 @@ const T = {
|
||||
regenFailed: 'Reset failed. Please refresh and try again.',
|
||||
ariaShowPw: 'Show password',
|
||||
ariaHidePw: 'Hide password',
|
||||
changelogLink: 'Changelog',
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -178,10 +178,8 @@
|
||||
<a href="/llms.txt">llms.txt</a>
|
||||
<span data-i18n="sep"> · </span>
|
||||
<a href="https://gitea.refining.dev/refining/secrets" target="_blank" rel="noopener noreferrer" data-i18n="footRepo">源码仓库</a>
|
||||
{% if !is_logged_in %}
|
||||
<span data-i18n="sep"> · </span>
|
||||
<a href="/login" data-i18n="footLogin">登录</a>
|
||||
{% endif %}
|
||||
<a href="/changelog" data-i18n="footChangelog">变更记录</a>
|
||||
</footer>
|
||||
<script>
|
||||
const T = {
|
||||
@@ -200,7 +198,7 @@
|
||||
versionLabel: '版本',
|
||||
sep: ' · ',
|
||||
footRepo: '源码仓库',
|
||||
footLogin: '登录',
|
||||
footChangelog: '变更记录',
|
||||
},
|
||||
'zh-TW': {
|
||||
docTitle: 'Secrets MCP — 端到端加密的金鑰管理',
|
||||
@@ -217,7 +215,7 @@
|
||||
versionLabel: '版本',
|
||||
sep: ' · ',
|
||||
footRepo: '原始碼倉庫',
|
||||
footLogin: '登入',
|
||||
footChangelog: '變更記錄',
|
||||
},
|
||||
'en': {
|
||||
docTitle: 'Secrets MCP — End-to-end encrypted secrets',
|
||||
@@ -234,7 +232,7 @@
|
||||
versionLabel: 'Version',
|
||||
sep: ' · ',
|
||||
footRepo: 'Source repository',
|
||||
footLogin: 'Sign in',
|
||||
footChangelog: 'Changelog',
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user