| 1 | <!doctype html> |
| 2 | <html lang="en"> |
| 3 | <head> |
| 4 | <meta charset="utf-8" /> |
| 5 | <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| 6 | <title>Reasonix — DeepSeek-native coding agent for your terminal</title> |
| 7 | <meta name="description" content="Open-source AI coding agent for your terminal, engineered around DeepSeek's byte-stable prefix cache. Long sessions hold 90%+ cache hit and input-token cost collapses to ~1/5. A single Go binary. npm · Homebrew · desktop. MIT." /> |
| 8 | <link rel="canonical" href="https://esengine.github.io/DeepSeek-Reasonix/" /> |
| 9 | <link rel="icon" href="favicon.svg" type="image/svg+xml" /> |
| 10 | <meta property="og:title" content="Reasonix — DeepSeek-native coding agent" /> |
| 11 | <meta property="og:description" content="Cache-first AI coding agent for your terminal. A single Go binary. npm · Homebrew · desktop. MIT." /> |
| 12 | <meta property="og:url" content="https://esengine.github.io/DeepSeek-Reasonix/" /> |
| 13 | <style> |
| 14 | :root{ |
| 15 | --bg:#f7f6f3; --paper:#fdfdfc; --ink:#16171a; --body:#3c3e44; --muted:#74777e; --faint:#9b9ea5; |
| 16 | --line:#e7e5df; --line-2:#dcd9d1; --accent:#2f5bd6; --code-bg:#17181c; --code-fg:#d7dae1; |
| 17 | --maxw:1060px; --radius:12px; |
| 18 | --mono:ui-monospace,"SF Mono","JetBrains Mono",Menlo,Consolas,monospace; |
| 19 | --sans:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"PingFang SC","Microsoft YaHei",sans-serif; |
| 20 | --serif:"Iowan Old Style","Palatino Linotype",Georgia,"Songti SC",serif; |
| 21 | } |
| 22 | *{box-sizing:border-box} |
| 23 | html{scroll-behavior:smooth} |
| 24 | body{margin:0;background:var(--bg);color:var(--body);font-family:var(--sans);font-size:17px;line-height:1.65;-webkit-font-smoothing:antialiased} |
| 25 | a{color:inherit;text-decoration:none} |
| 26 | ::selection{background:#dfe6fb} |
| 27 | .wrap{max-width:var(--maxw);margin:0 auto;padding:0 28px} |
| 28 | |
| 29 | nav{position:sticky;top:0;z-index:40;background:rgba(247,246,243,.82);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)} |
| 30 | .nav{display:flex;align-items:center;justify-content:space-between;height:64px} |
| 31 | .brand{display:flex;align-items:center;gap:9px;font-weight:600;font-size:17px;letter-spacing:-.02em;color:var(--ink)} |
| 32 | .brand .mk{width:22px;height:22px;border-radius:6px;background:var(--ink);color:#fff;display:grid;place-items:center;font-size:13px;font-weight:700} |
| 33 | .nav-links{display:flex;gap:30px} |
| 34 | .nav-links a{color:var(--muted);font-size:15px;transition:color .15s} |
| 35 | .nav-links a:hover{color:var(--ink)} |
| 36 | .nav-right{display:flex;align-items:center;gap:18px} |
| 37 | .lang{font-family:var(--mono);font-size:13px;color:var(--muted);background:none;border:none;cursor:pointer;padding:4px} |
| 38 | .lang:hover{color:var(--ink)} |
| 39 | @media(max-width:720px){.nav-links{display:none}} |
| 40 | |
| 41 | .btn{display:inline-flex;align-items:center;gap:8px;font-weight:500;font-size:15px;padding:11px 20px;border-radius:9px;transition:.16s;cursor:pointer;border:1px solid transparent;white-space:nowrap} |
| 42 | .btn-dark{background:var(--ink);color:#fff;border-color:var(--ink)} |
| 43 | .btn-dark:hover{background:#000} |
| 44 | .btn-line{background:transparent;color:var(--ink);border-color:var(--line-2)} |
| 45 | .btn-line:hover{border-color:var(--ink)} |
| 46 | |
| 47 | /* hero */ |
| 48 | .hero{text-align:center;padding:104px 0 0} |
| 49 | .kicker{font-family:var(--mono);font-size:13px;letter-spacing:.04em;color:var(--muted);margin-bottom:30px} |
| 50 | .kicker .b{color:var(--ink)} |
| 51 | h1{font-size:clamp(40px,6.4vw,74px);line-height:1.05;letter-spacing:-.04em;font-weight:600;color:var(--ink);margin:0 auto 26px;max-width:14ch} |
| 52 | h1 em{font-style:italic;font-family:var(--serif);font-weight:500;color:var(--accent)} |
| 53 | .lede{max-width:600px;margin:0 auto 40px;color:var(--muted);font-size:clamp(17px,2.1vw,20px);line-height:1.6} |
| 54 | .lede b{color:var(--ink);font-weight:500} |
| 55 | .cta{display:flex;gap:12px;justify-content:center;flex-wrap:wrap} |
| 56 | .install{display:inline-flex;align-items:center;gap:16px;margin:34px auto 0;font-family:var(--mono);font-size:15px;color:var(--ink); |
| 57 | background:var(--paper);border:1px solid var(--line-2);border-radius:10px;padding:13px 12px 13px 18px} |
| 58 | .install .p{color:var(--faint)} |
| 59 | .cp{cursor:pointer;background:var(--bg);border:1px solid var(--line-2);border-radius:7px;color:var(--muted);font-family:var(--mono);font-size:12px;padding:6px 11px;transition:.15s} |
| 60 | .cp:hover{color:var(--ink);border-color:var(--line-2)} |
| 61 | .cp.ok{color:#1a8f5a;border-color:#bfe3cd} |
| 62 | |
| 63 | /* terminal */ |
| 64 | .term{max-width:720px;margin:72px auto 0;text-align:left;background:var(--code-bg);border-radius:14px;overflow:hidden; |
| 65 | box-shadow:0 1px 0 rgba(0,0,0,.04),0 26px 60px -32px rgba(20,22,40,.5)} |
| 66 | .tbar{display:flex;align-items:center;gap:7px;padding:13px 16px;border-bottom:1px solid rgba(255,255,255,.07)} |
| 67 | .tbar i{width:11px;height:11px;border-radius:50%;background:#3a3d46;display:inline-block} |
| 68 | .tbar span{margin-left:10px;font-family:var(--mono);font-size:12px;color:#71757f} |
| 69 | .tbody{padding:20px 22px;font-family:var(--mono);font-size:13px;line-height:1.95;color:var(--code-fg);white-space:pre} |
| 70 | .tbody .u{color:#6f9bff}.tbody .i{color:#8fb4ff}.tbody .d{color:#6a6e78} |
| 71 | .tbody .k{color:#8fd6b0}.tbody .e{color:#c7a3f0}.tbody .c{color:#5a5e68} |
| 72 | @media(max-width:560px){.tbody{font-size:11.5px}} |
| 73 | |
| 74 | /* sections */ |
| 75 | section{padding:108px 0} |
| 76 | .lab{font-family:var(--mono);font-size:13px;letter-spacing:.04em;color:var(--accent);margin-bottom:16px} |
| 77 | h2{font-size:clamp(28px,4vw,42px);line-height:1.12;letter-spacing:-.03em;font-weight:600;color:var(--ink);margin:0 0 16px;max-width:18ch} |
| 78 | .sub{color:var(--muted);font-size:18px;max-width:560px;margin:0} |
| 79 | .head{margin-bottom:48px} |
| 80 | |
| 81 | /* install tabs */ |
| 82 | .tabs{display:flex;gap:24px;border-bottom:1px solid var(--line);margin-bottom:0} |
| 83 | .tab{font-size:15px;font-weight:500;color:var(--muted);background:none;border:none;border-bottom:2px solid transparent;padding:0 0 14px;cursor:pointer;transition:.15s;margin-bottom:-1px} |
| 84 | .tab.on{color:var(--ink);border-bottom-color:var(--ink)} |
| 85 | .tab:hover{color:var(--ink)} |
| 86 | .panel{display:none}.panel.on{display:block} |
| 87 | .block{position:relative;background:var(--code-bg);border-radius:12px;margin-top:24px;overflow:hidden} |
| 88 | .block pre{margin:0;padding:24px 26px;font-family:var(--mono);font-size:14px;line-height:2.1;color:var(--code-fg);white-space:pre-wrap;overflow-x:auto} |
| 89 | .block .p{color:#6f9bff}.block .c{color:#6a6e78} |
| 90 | .block .cp{position:absolute;top:14px;right:14px;background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.12);color:#aeb2bc} |
| 91 | .block .cp:hover{color:#fff} |
| 92 | .undertext{margin-top:16px;color:var(--muted);font-size:15px} |
| 93 | .undertext code{font-family:var(--mono);font-size:13px;background:var(--paper);border:1px solid var(--line);padding:1px 6px;border-radius:5px;color:var(--ink)} |
| 94 | .undertext a{color:var(--accent)} |
| 95 | |
| 96 | .dls{margin-top:24px;border-top:1px solid var(--line)} |
| 97 | .dl{display:flex;align-items:center;gap:18px;padding:18px 6px;border-bottom:1px solid var(--line);transition:.15s} |
| 98 | .dl:hover{background:var(--paper)} |
| 99 | .dl .os{font-weight:600;color:var(--ink);min-width:84px;font-size:15.5px} |
| 100 | .dl .fn{font-family:var(--mono);font-size:13.5px;color:var(--body);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} |
| 101 | .dl .ar{font-size:13px;color:var(--faint);white-space:nowrap} |
| 102 | .dl .go{color:var(--accent);font-family:var(--mono);font-size:14px} |
| 103 | @media(max-width:600px){.dl .ar{display:none}.dl .fn{font-size:12px}} |
| 104 | |
| 105 | /* features */ |
| 106 | .grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0;border-top:1px solid var(--line)} |
| 107 | @media(max-width:820px){.grid{grid-template-columns:repeat(2,1fr)}} |
| 108 | @media(max-width:540px){.grid{grid-template-columns:1fr}} |
| 109 | .feat{padding:34px 30px 34px 0;border-bottom:1px solid var(--line)} |
| 110 | .feat .n{font-family:var(--mono);font-size:12.5px;color:var(--faint);margin-bottom:14px} |
| 111 | .feat h3{font-size:18px;font-weight:600;color:var(--ink);margin:0 0 8px;letter-spacing:-.01em} |
| 112 | .feat p{margin:0;color:var(--muted);font-size:15px;line-height:1.6} |
| 113 | .feat code{font-family:var(--mono);font-size:12.5px;color:var(--ink)} |
| 114 | |
| 115 | /* stats */ |
| 116 | .why{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center} |
| 117 | @media(max-width:760px){.why{grid-template-columns:1fr;gap:40px}} |
| 118 | .nums{display:flex;flex-direction:column;gap:28px} |
| 119 | .num{display:flex;align-items:baseline;gap:18px;border-top:1px solid var(--line);padding-top:22px} |
| 120 | .num .v{font-size:40px;font-weight:600;letter-spacing:-.03em;color:var(--ink);min-width:120px} |
| 121 | .num .l{color:var(--muted);font-size:15px} |
| 122 | |
| 123 | footer{border-top:1px solid var(--line);padding:44px 0} |
| 124 | .foot{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:16px;color:var(--faint);font-size:14.5px} |
| 125 | .foot a{color:var(--muted)}.foot a:hover{color:var(--ink)} |
| 126 | .foot-links{display:flex;gap:26px;flex-wrap:wrap} |
| 127 | |
| 128 | [data-zh]{display:none} |
| 129 | html[lang="zh"] [data-en]{display:none} |
| 130 | html[lang="zh"] [data-zh]{display:inline} |
| 131 | html[lang="zh"] [data-zh].blk{display:block} |
| 132 | html[lang="zh"] h1,html[lang="zh"] h2{letter-spacing:-.02em} |
| 133 | </style> |
| 134 | </head> |
| 135 | <body> |
| 136 | <nav> |
| 137 | <div class="wrap nav"> |
| 138 | <a class="brand" href="#top"><span class="mk">R</span>Reasonix</a> |
| 139 | <div class="nav-links"> |
| 140 | <a href="#install" data-en>Install</a><a href="#install" data-zh>安装</a> |
| 141 | <a href="#features" data-en>Features</a><a href="#features" data-zh>特性</a> |
| 142 | <a href="#why" data-en>Why DeepSeek</a><a href="#why" data-zh>为何 DeepSeek</a> |
| 143 | <a href="https://github.com/esengine/DeepSeek-Reasonix">GitHub</a> |
| 144 | </div> |
| 145 | <div class="nav-right"> |
| 146 | <button class="lang" id="lang">中文</button> |
| 147 | <a class="btn btn-dark" href="#install"><span data-en>Get started</span><span data-zh>开始</span></a> |
| 148 | </div> |
| 149 | </div> |
| 150 | </nav> |
| 151 | |
| 152 | <a id="top"></a> |
| 153 | <header class="hero wrap"> |
| 154 | <div class="kicker"><span class="b">v1.0.0</span> · <span data-en>a ground-up rewrite in Go · open source, MIT</span><span data-zh>Go 全新重写 · 开源 MIT</span></div> |
| 155 | <h1> |
| 156 | <span data-en>A <em>DeepSeek</em>-native agent for your terminal.</span> |
| 157 | <span data-zh><em>DeepSeek</em> 原生的终端编码 Agent。</span> |
| 158 | </h1> |
| 159 | <p class="lede"> |
| 160 | <span data-en>The loop is append-only, aligned to DeepSeek's byte-stable prefix cache — so long sessions hold <b>90%+ cache hit</b> and input-token cost collapses to <b>~1/5</b>. One Go binary. Terminal-first.</span> |
| 161 | <span data-zh>运行循环 append-only,对齐 DeepSeek 字节稳定的 prefix-cache —— 长会话缓存命中 <b>90%+</b>,输入 token 成本降到 <b>约 1/5</b>。单个 Go 二进制,终端优先。</span> |
| 162 | </p> |
| 163 | <div class="cta"> |
| 164 | <a class="btn btn-dark" href="#install"><span data-en>Get started</span><span data-zh>开始使用</span></a> |
| 165 | <a class="btn btn-line" href="https://github.com/esengine/DeepSeek-Reasonix"><span data-en>View on GitHub</span><span data-zh>在 GitHub 查看</span></a> |
| 166 | </div> |
| 167 | <div class="install"> |
| 168 | <span><span class="p">$ </span>npm i -g reasonix</span> |
| 169 | <button class="cp" data-copy="npm i -g reasonix"><span data-en>Copy</span><span data-zh>复制</span></button> |
| 170 | </div> |
| 171 | |
| 172 | <div class="term"> |
| 173 | <div class="tbar"><i></i><i></i><i></i><span>~/app — reasonix</span></div> |
| 174 | <div class="tbody"><span class="u">$</span> reasonix |
| 175 | <span class="i">reasonix v1.0.0 · model deepseek-v4-flash · ~/app</span> |
| 176 | <span class="d">cache 94.2% hit · session 18m · cost $0.043</span> |
| 177 | <span class="u">›</span> add retry with backoff to the http client |
| 178 | <span class="e">edit</span> internal/net/client.go <span class="c">+24 −3</span> |
| 179 | <span class="e">edit</span> internal/net/client_test.go <span class="c">+41 −0</span> |
| 180 | <span class="k">✓</span> go test ./internal/net/ ok 0.21s |
| 181 | <span class="d">2 files · cache 94.2% → 95.1%</span></div> |
| 182 | </div> |
| 183 | </header> |
| 184 | |
| 185 | <section id="install" class="wrap"> |
| 186 | <div class="head"> |
| 187 | <div class="lab" data-en>Install</div><div class="lab" data-zh>安装</div> |
| 188 | <h2><span data-en>Up and running in one line.</span><span data-zh>一行命令,跑起来。</span></h2> |
| 189 | <p class="sub"><span data-en>The npm package pulls the prebuilt native binary for your platform — no Node runtime needed to run it.</span><span data-zh>npm 包自动拉取对应平台的预编译原生二进制 —— 运行时不需要 Node。</span></p> |
| 190 | </div> |
| 191 | <div class="tabs"> |
| 192 | <button class="tab on" data-tab="npm">npm</button> |
| 193 | <button class="tab" data-tab="brew">Homebrew</button> |
| 194 | <button class="tab" data-tab="desk"><span data-en>Desktop</span><span data-zh>桌面端</span></button> |
| 195 | </div> |
| 196 | <div class="panel on" data-panel="npm"> |
| 197 | <div class="block"><button class="cp" data-copy="npm i -g reasonix |
| 198 | reasonix setup |
| 199 | reasonix"><span data-en>Copy</span><span data-zh>复制</span></button><pre><span class="p">$</span> npm i -g reasonix |
| 200 | <span class="p">$</span> reasonix setup <span class="c"># config wizard → ./reasonix.toml</span> |
| 201 | <span class="p">$</span> reasonix <span class="c"># or: reasonix run "implement the TODOs"</span></pre></div> |
| 202 | <p class="undertext"><span data-en>Any OS · macOS, Linux, Windows × amd64/arm64. Short alias <code>dsnix</code> too.</span><span data-zh>任意系统 · macOS、Linux、Windows × amd64/arm64。</span></p> |
| 203 | </div> |
| 204 | <div class="panel" data-panel="brew"> |
| 205 | <div class="block"><button class="cp" data-copy="brew install esengine/reasonix/reasonix"><span data-en>Copy</span><span data-zh>复制</span></button><pre><span class="p">$</span> brew install esengine/reasonix/reasonix</pre></div> |
| 206 | <p class="undertext"><span data-en>macOS. The cask pulls the archive from the latest release.</span><span data-zh>macOS。cask 从最新 release 拉取归档。</span></p> |
| 207 | </div> |
| 208 | <div class="panel" data-panel="desk"> |
| 209 | <div class="dls"> |
| 210 | <a class="dl" href="https://dl.reasonix.io/latest/Reasonix-darwin-arm64.zip" download> |
| 211 | <span class="os">macOS</span><span class="fn">Reasonix-darwin-arm64.zip</span><span class="ar" data-en>universal · Intel + Apple Silicon</span><span class="ar" data-zh>通用 · Intel + Apple Silicon</span><span class="go">↓</span> |
| 212 | </a> |
| 213 | <a class="dl" href="https://dl.reasonix.io/latest/Reasonix-windows-amd64-installer.exe" download> |
| 214 | <span class="os">Windows</span><span class="fn">Reasonix-windows-amd64-installer.exe</span><span class="ar" data-en>installer · x64</span><span class="ar" data-zh>安装器 · x64</span><span class="go">↓</span> |
| 215 | </a> |
| 216 | <a class="dl" href="https://dl.reasonix.io/latest/Reasonix-linux-amd64.tar.gz" download> |
| 217 | <span class="os">Linux</span><span class="fn">Reasonix-linux-amd64.tar.gz</span><span class="ar" data-en>x64</span><span class="ar" data-zh>x64</span><span class="go">↓</span> |
| 218 | </a> |
| 219 | </div> |
| 220 | <p class="undertext"><span data-en>Served from the R2 CDN (fast worldwide). Or browse <a href="https://github.com/esengine/DeepSeek-Reasonix/releases">all releases on GitHub</a>.</span><span data-zh>经 R2 CDN 分发(全球加速)。或在 <a href="https://github.com/esengine/DeepSeek-Reasonix/releases">GitHub releases</a> 浏览全部。</span></p> |
| 221 | </div> |
| 222 | </section> |
| 223 | |
| 224 | <section id="features" class="wrap"> |
| 225 | <div class="head"> |
| 226 | <div class="lab" data-en>Features</div><div class="lab" data-zh>特性</div> |
| 227 | <h2><span data-en>Built for long, cheap sessions.</span><span data-zh>为长会话、低成本而生。</span></h2> |
| 228 | </div> |
| 229 | <div class="grid"> |
| 230 | <div class="feat"><div class="n">01</div><h3 data-en>Cache-first loop</h3><h3 data-zh>缓存优先循环</h3><p data-en>Append-only history aligned to DeepSeek's prefix cache. 90%+ hit on long sessions; input tokens bill at ~1/5.</p><p data-zh>append-only 历史对齐 DeepSeek prefix-cache。长会话 90%+ 命中,输入 token 约 1/5 计费。</p></div> |
| 231 | <div class="feat"><div class="n">02</div><h3 data-en>Single Go binary</h3><h3 data-zh>单个 Go 二进制</h3><p data-en>CGO-free, cross-compiled for darwin/linux/windows × amd64/arm64. No Node runtime.</p><p data-zh>无 CGO,交叉编译覆盖 darwin/linux/windows × amd64/arm64。运行不需要 Node。</p></div> |
| 232 | <div class="feat"><div class="n">03</div><h3>MCP first-class</h3><p data-en>stdio, SSE, streamable HTTP. External servers merge their tools into one registry under a prefix.</p><p data-zh>stdio、SSE、streamable HTTP。外部服务器的工具以前缀合并进同一 registry。</p></div> |
| 233 | <div class="feat"><div class="n">04</div><h3 data-en>Plan mode + sandbox</h3><h3 data-zh>计划模式 + 沙箱</h3><p data-en><code>/plan</code> asks the model to plan first; Permissions and the workspace sandbox still govern every tool call.</p><p data-zh><code>/plan</code> 要求模型先规划;每次工具调用仍由权限与工作区沙箱控制。</p></div> |
| 234 | <div class="feat"><div class="n">05</div><h3 data-en>Subagents & skills</h3><h3 data-zh>子智能体与技能</h3><p data-en>explore / research / review / security-review agents, plus Markdown skill scripts with isolated tools.</p><p data-zh>explore / research / review / security-review 子智能体,加 Markdown 技能脚本与隔离工具。</p></div> |
| 235 | <div class="feat"><div class="n">06</div><h3 data-en>Terminal-native</h3><h3 data-zh>终端原生</h3><p data-en>Not another IDE plugin. <code>git diff</code> handles diffs, <code>ls</code> handles trees — the terminal is the workspace.</p><p data-zh>不是又一个 IDE 插件。diff 交给 <code>git diff</code> —— 终端就是工作面板。</p></div> |
| 236 | </div> |
| 237 | </section> |
| 238 | |
| 239 | <section id="why" class="wrap"> |
| 240 | <div class="why"> |
| 241 | <div> |
| 242 | <div class="lab" data-en>Why DeepSeek</div><div class="lab" data-zh>为何 DeepSeek</div> |
| 243 | <h2><span data-en>The cheapness is the point.</span><span data-zh>便宜,就是核心。</span></h2> |
| 244 | <p class="sub"><span data-en>Most agents pay full price for the same growing prompt every turn. Reasonix keeps the prefix byte-identical so DeepSeek's cache does the heavy lifting.</span><span data-zh>多数 agent 每回合都为同一段不断增长的 prompt 付全价。Reasonix 让前缀逐字节稳定,让 DeepSeek 的缓存替你扛下来。</span></p> |
| 245 | </div> |
| 246 | <div class="nums"> |
| 247 | <div class="num"><div class="v">90%+</div><div class="l"><span data-en>cache hit on long sessions</span><span data-zh>长会话缓存命中</span></div></div> |
| 248 | <div class="num"><div class="v">~1/5</div><div class="l"><span data-en>input-token cost</span><span data-zh>输入 token 成本</span></div></div> |
| 249 | <div class="num"><div class="v">0</div><div class="l"><span data-en>Node runtime to run it</span><span data-zh>运行所需 Node</span></div></div> |
| 250 | </div> |
| 251 | </div> |
| 252 | </section> |
| 253 | |
| 254 | <footer> |
| 255 | <div class="wrap foot"> |
| 256 | <div>© 2026 Reasonix · <span data-en>MIT licensed</span><span data-zh>MIT 许可</span></div> |
| 257 | <div class="foot-links"> |
| 258 | <a href="https://github.com/esengine/DeepSeek-Reasonix">GitHub</a> |
| 259 | <a href="https://www.npmjs.com/package/reasonix">npm</a> |
| 260 | <a href="https://platform.deepseek.com" target="_blank" rel="noreferrer">DeepSeek</a> |
| 261 | <a href="https://github.com/esengine/DeepSeek-Reasonix/releases"><span data-en>Releases</span><span data-zh>下载</span></a> |
| 262 | </div> |
| 263 | </div> |
| 264 | </footer> |
| 265 | |
| 266 | <script> |
| 267 | var html=document.documentElement, langBtn=document.getElementById('lang'); |
| 268 | function setLang(l){html.lang=l;langBtn.textContent=l==='zh'?'EN':'中文';try{localStorage.setItem('rx-lang',l)}catch(e){}} |
| 269 | var saved; try{saved=localStorage.getItem('rx-lang')}catch(e){} |
| 270 | setLang(saved||((navigator.language||'').toLowerCase().indexOf('zh')===0?'zh':'en')); |
| 271 | langBtn.onclick=function(){setLang(html.lang==='zh'?'en':'zh')}; |
| 272 | |
| 273 | document.querySelectorAll('.tab').forEach(function(t){ |
| 274 | t.onclick=function(){ |
| 275 | document.querySelectorAll('.tab').forEach(function(x){x.classList.remove('on')}); |
| 276 | document.querySelectorAll('.panel').forEach(function(x){x.classList.remove('on')}); |
| 277 | t.classList.add('on'); |
| 278 | document.querySelector('[data-panel="'+t.dataset.tab+'"]').classList.add('on'); |
| 279 | }; |
| 280 | }); |
| 281 | |
| 282 | document.querySelectorAll('.cp').forEach(function(b){ |
| 283 | b.onclick=function(){ |
| 284 | navigator.clipboard.writeText(b.dataset.copy).then(function(){ |
| 285 | var prev=b.innerHTML; b.classList.add('ok'); |
| 286 | b.innerHTML='<span data-en>Copied</span><span data-zh>已复制</span>'; |
| 287 | setTimeout(function(){b.innerHTML=prev;b.classList.remove('ok')},1400); |
| 288 | }); |
| 289 | }; |
| 290 | }); |
| 291 | </script> |
| 292 | </body> |
| 293 | </html> |
| 294 |