docs(web,readme): taste pass — fix stale refs, tighten design rhythm
Polish fixes (12): - INSTALL.md: drop duplicate code block; doc CODEWHALE_VERSION canonical env var; fix example mirror URLs /DeepSeek-TUI/ → /CodeWhale/; remove stale "Once npm publication resumes" conditional - footer.tsx: fix Gitee mirror URL deepseek-tui → CodeWhale - globals.css: update seal CSS shadows from old cream rgba(244,241,232) to paper white rgba(255,255,255) - web/README.md: update palette description cream #FAF6EE → white #FFFFFF - nav.tsx: fix zh-only date strip (第…期) and API label (在线) — now "Edition …" / "API · Online" in en mode - page.tsx: hardcoded v0.8.56 → dynamic facts.version - README.md: merge duplicate Contributing sections - README.ja-JP/vi: parenthesize untranslated Chinese thank-you blurbs Design rhythm (9): - ThinkingTrace section: py-16→py-20, bg-paper-deep, hairlines for reveal - Judgment stack: py-16→py-12; middle cell bg-paper-deep for ABA rhythm - Maintainer loop: py-16→py-14; step numbers grow 01→04 - How it works: py-16→py-12 - Join in closer: py-16→py-20 (dark section breathes) - Ticker: LIVE label shrunk to annotation weight
This commit is contained in:
+2
-2
@@ -142,8 +142,8 @@ CodeWhale は、エージェントが実際のワークスペースで**どう
|
|||||||
|
|
||||||
CodeWhale が存在するのは、それを使い、壊し、直してくれる人たちのおかげです。
|
CodeWhale が存在するのは、それを使い、壊し、直してくれる人たちのおかげです。
|
||||||
|
|
||||||
- **[DeepSeek](https://github.com/deepseek-ai)** ―― このプロジェクトを始められたモデルと支援。感謝 DeepSeek 提供模型与支持。
|
- **[DeepSeek](https://github.com/deepseek-ai)** ―― このプロジェクトを始められたモデルと支援。(感謝 DeepSeek 提供模型与支持。)
|
||||||
- **[DataWhale](https://github.com/datawhalechina)** 🐋 ―― 支援と、「鯨兄弟」ファミリーへの歓迎に感謝します。
|
- **[DataWhale](https://github.com/datawhalechina)** 🐋 ―― 支援と、「鯨兄弟」ファミリーへの歓迎に感謝します。(感谢 DataWhale 的支持。)
|
||||||
- **[OpenWarp](https://github.com/zerx-lab/warp)** と
|
- **[OpenWarp](https://github.com/zerx-lab/warp)** と
|
||||||
**[Open Design](https://github.com/nexu-io/open-design)** ―― より良いターミナルエージェント体験の協業に感謝します。
|
**[Open Design](https://github.com/nexu-io/open-design)** ―― より良いターミナルエージェント体験の協業に感謝します。
|
||||||
- **すべてのコントリビューター** ―― PR ごとの完全な記録は
|
- **すべてのコントリビューター** ―― PR ごとの完全な記録は
|
||||||
|
|||||||
@@ -189,12 +189,6 @@ CodeWhale exists because of the people who use it, break it, and fix it.
|
|||||||
- **Every contributor** — the full per-PR record lives in
|
- **Every contributor** — the full per-PR record lives in
|
||||||
[docs/CONTRIBUTORS.md](docs/CONTRIBUTORS.md). Thank you.
|
[docs/CONTRIBUTORS.md](docs/CONTRIBUTORS.md). Thank you.
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
See [CONTRIBUTING.md](CONTRIBUTING.md). Pull requests welcome — check the
|
|
||||||
[open issues](https://github.com/Hmbown/CodeWhale/issues) for good first
|
|
||||||
contributions.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT](LICENSE)
|
[MIT](LICENSE)
|
||||||
|
|||||||
+2
-2
@@ -180,9 +180,9 @@ nó và chỉ dùng các công cụ.
|
|||||||
CodeWhale tồn tại nhờ những người dùng nó, làm hỏng nó, và sửa nó.
|
CodeWhale tồn tại nhờ những người dùng nó, làm hỏng nó, và sửa nó.
|
||||||
|
|
||||||
- **[DeepSeek](https://github.com/deepseek-ai)** — những mô hình và sự hỗ trợ đã
|
- **[DeepSeek](https://github.com/deepseek-ai)** — những mô hình và sự hỗ trợ đã
|
||||||
giúp dự án này khởi đầu. 感谢 DeepSeek 提供模型与支持。
|
giúp dự án này khởi đầu.(感谢 DeepSeek 提供模型与支持。)
|
||||||
- **[DataWhale](https://github.com/datawhalechina)** 🐋 — vì sự hỗ trợ và vì đã
|
- **[DataWhale](https://github.com/datawhalechina)** 🐋 — vì sự hỗ trợ và vì đã
|
||||||
đón chúng tôi vào gia đình Whale Brother. 感谢 DataWhale 的支持。
|
đón chúng tôi vào gia đình Whale Brother.(感谢 DataWhale 的支持。)
|
||||||
- **[OpenWarp](https://github.com/zerx-lab/warp)** và
|
- **[OpenWarp](https://github.com/zerx-lab/warp)** và
|
||||||
**[Open Design](https://github.com/nexu-io/open-design)** — vì đã hợp tác xây
|
**[Open Design](https://github.com/nexu-io/open-design)** — vì đã hợp tác xây
|
||||||
dựng một trải nghiệm terminal-agent tốt hơn.
|
dựng một trải nghiệm terminal-agent tốt hơn.
|
||||||
|
|||||||
+5
-9
@@ -92,11 +92,6 @@ npm install -g codewhale
|
|||||||
codewhale
|
codewhale
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install -g codewhale
|
|
||||||
codewhale
|
|
||||||
```
|
|
||||||
|
|
||||||
`postinstall` downloads the right pair of binaries from the matching GitHub
|
`postinstall` downloads the right pair of binaries from the matching GitHub
|
||||||
release, verifies a SHA-256 manifest, and exposes both `codewhale` and
|
release, verifies a SHA-256 manifest, and exposes both `codewhale` and
|
||||||
`codewhale-tui` on your `PATH`.
|
`codewhale-tui` on your `PATH`.
|
||||||
@@ -105,14 +100,15 @@ Useful environment variables:
|
|||||||
|
|
||||||
| Variable | Purpose |
|
| Variable | Purpose |
|
||||||
| ----------------------------------- | -------------------------------------------------------------------------------------- |
|
| ----------------------------------- | -------------------------------------------------------------------------------------- |
|
||||||
| `DEEPSEEK_TUI_VERSION` | Pin which release the wrapper downloads (defaults to `deepseekBinaryVersion`) |
|
| `CODEWHALE_VERSION` | Pin which release the wrapper downloads (canonical) |
|
||||||
|
| `DEEPSEEK_TUI_VERSION` | Legacy alias for `CODEWHALE_VERSION` (defaults to `codewhaleBinaryVersion`) |
|
||||||
| `DEEPSEEK_TUI_GITHUB_REPO` | Point the downloader at a fork (`owner/repo`) |
|
| `DEEPSEEK_TUI_GITHUB_REPO` | Point the downloader at a fork (`owner/repo`) |
|
||||||
| `DEEPSEEK_TUI_RELEASE_BASE_URL` | Override the download root (e.g. an internal mirror or release-asset proxy) |
|
| `DEEPSEEK_TUI_RELEASE_BASE_URL` | Override the download root (e.g. an internal mirror or release-asset proxy) |
|
||||||
| `DEEPSEEK_TUI_FORCE_DOWNLOAD=1` | Re-download even if a cached binary marker matches |
|
| `DEEPSEEK_TUI_FORCE_DOWNLOAD=1` | Re-download even if a cached binary marker matches |
|
||||||
| `DEEPSEEK_TUI_DISABLE_INSTALL=1` | Skip the `postinstall` download entirely (CI smoke, vendored binaries) |
|
| `DEEPSEEK_TUI_DISABLE_INSTALL=1` | Skip the `postinstall` download entirely (CI smoke, vendored binaries) |
|
||||||
| `DEEPSEEK_TUI_OPTIONAL_INSTALL=1` | Don't fail `npm install` on download/extract errors — useful in CI matrices |
|
| `DEEPSEEK_TUI_OPTIONAL_INSTALL=1` | Don't fail `npm install` on download/extract errors — useful in CI matrices |
|
||||||
|
|
||||||
> **Slow npm download from mainland China?** Once npm publication resumes, if `npm install` itself is slow
|
> **Slow npm download from mainland China?** If `npm install` itself is slow
|
||||||
> (not just the postinstall binary download), use an npm registry mirror:
|
> (not just the postinstall binary download), use an npm registry mirror:
|
||||||
> ```bash
|
> ```bash
|
||||||
> npm config set registry https://registry.npmmirror.com
|
> npm config set registry https://registry.npmmirror.com
|
||||||
@@ -579,7 +575,7 @@ If you operate a binary asset mirror, `codewhale update` can use it directly:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
DEEPSEEK_TUI_VERSION=X.Y.Z \
|
DEEPSEEK_TUI_VERSION=X.Y.Z \
|
||||||
DEEPSEEK_TUI_RELEASE_BASE_URL=https://your-mirror.example.com/DeepSeek-TUI/vX.Y.Z/ \
|
DEEPSEEK_TUI_RELEASE_BASE_URL=https://your-mirror.example.com/CodeWhale/vX.Y.Z/ \
|
||||||
codewhale update
|
codewhale update
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -706,7 +702,7 @@ Use one of these paths:
|
|||||||
2. Mirror the release assets internally and set `DEEPSEEK_TUI_RELEASE_BASE_URL`:
|
2. Mirror the release assets internally and set `DEEPSEEK_TUI_RELEASE_BASE_URL`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export DEEPSEEK_TUI_RELEASE_BASE_URL=https://your-mirror.example.com/DeepSeek-TUI/
|
export DEEPSEEK_TUI_RELEASE_BASE_URL=https://your-mirror.example.com/CodeWhale/
|
||||||
codewhale
|
codewhale
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -94,7 +94,7 @@ web/
|
|||||||
|
|
||||||
"Yamen tech": Qing memorial document × WeChat news feed × Bloomberg terminal.
|
"Yamen tech": Qing memorial document × WeChat news feed × Bloomberg terminal.
|
||||||
|
|
||||||
- **Palette**: cream paper `#FAF6EE`, ink `#0A2540`, cinnabar red `#C8102E`, aged gold, jade green, cobalt blue.
|
- **Palette**: white paper `#FFFFFF`, cool gray `#F4F6FB`, ink `#0E0E10`, indigo `#4D6BFE`, jade green, cobalt blue.
|
||||||
- **Type**: Fraunces (display), IBM Plex Sans (body), JetBrains Mono (UI/code), Noto Serif SC (decorative CJK anchors).
|
- **Type**: Fraunces (display), IBM Plex Sans (body), JetBrains Mono (UI/code), Noto Serif SC (decorative CJK anchors).
|
||||||
- **Structure**: hairline 1px dividers, multi-column grids, big tabular numbers, surgical use of red for "hot" markers, decorative Chinese-seal squares as section anchors.
|
- **Structure**: hairline 1px dividers, multi-column grids, big tabular numbers, surgical use of red for "hot" markers, decorative Chinese-seal squares as section anchors.
|
||||||
|
|
||||||
|
|||||||
@@ -242,7 +242,8 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
|||||||
<StatGrid stats={stats} />
|
<StatGrid stats={stats} />
|
||||||
|
|
||||||
{/* SEE HOW IT DECIDES — real reasoning traces prove the constitution operates */}
|
{/* SEE HOW IT DECIDES — real reasoning traces prove the constitution operates */}
|
||||||
<section className="mx-auto max-w-[1400px] px-6 py-16">
|
<section className="bg-paper-deep hairline-t hairline-b">
|
||||||
|
<div className="mx-auto max-w-[1400px] px-6 py-20">
|
||||||
<div className="flex items-baseline gap-4 mb-3 hairline-b pb-4">
|
<div className="flex items-baseline gap-4 mb-3 hairline-b pb-4">
|
||||||
<Seal char="判" />
|
<Seal char="判" />
|
||||||
<h2 className="font-display">
|
<h2 className="font-display">
|
||||||
@@ -260,10 +261,11 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
|||||||
? "这些是真实推理的忠实摘录,非杜撰。宪法不是墙上的口号,而是模型决策时真正遵循的顺序。"
|
? "这些是真实推理的忠实摘录,非杜撰。宪法不是墙上的口号,而是模型决策时真正遵循的顺序。"
|
||||||
: "Faithful excerpts from real reasoning — not invented. The constitution isn't a poster on the wall; it's the order the model actually follows when it decides."}
|
: "Faithful excerpts from real reasoning — not invented. The constitution isn't a poster on the wall; it's the order the model actually follows when it decides."}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* WHAT IT IS — the core ideas behind the harness */}
|
{/* WHAT IT IS — the core ideas behind the harness */}
|
||||||
<section className="mx-auto max-w-[1400px] px-6 py-16">
|
<section className="mx-auto max-w-[1400px] px-6 py-12">
|
||||||
<div className="flex items-baseline gap-4 mb-2 hairline-b pb-4">
|
<div className="flex items-baseline gap-4 mb-2 hairline-b pb-4">
|
||||||
<Seal char="是" />
|
<Seal char="是" />
|
||||||
<h2 className="font-display">
|
<h2 className="font-display">
|
||||||
@@ -286,7 +288,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
|||||||
Agent 不是模型卡片,也不是排行榜数字。它是这个终端、这个工作区、这个会话里的实例。先有地址,责任才有落点。
|
Agent 不是模型卡片,也不是排行榜数字。它是这个终端、这个工作区、这个会话里的实例。先有地址,责任才有落点。
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-6">
|
<div className="p-6 bg-paper-deep">
|
||||||
<div className="eyebrow mb-3">02 · 嵌套宪法</div>
|
<div className="eyebrow mb-3">02 · 嵌套宪法</div>
|
||||||
<h3 className="font-display text-xl mb-3">冲突时有法律</h3>
|
<h3 className="font-display text-xl mb-3">冲突时有法律</h3>
|
||||||
<p className="text-sm text-ink-soft leading-[1.9]">
|
<p className="text-sm text-ink-soft leading-[1.9]">
|
||||||
@@ -310,7 +312,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
|||||||
The agent is not a model card or leaderboard score. It is an instance in this terminal, this workspace, this session. Give it an address before you ask it to act.
|
The agent is not a model card or leaderboard score. It is an instance in this terminal, this workspace, this session. Give it an address before you ask it to act.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-6">
|
<div className="p-6 bg-paper-deep">
|
||||||
<div className="eyebrow mb-3">02 · nested constitution</div>
|
<div className="eyebrow mb-3">02 · nested constitution</div>
|
||||||
<h3 className="font-display text-xl mb-3">Conflict has law</h3>
|
<h3 className="font-display text-xl mb-3">Conflict has law</h3>
|
||||||
<p className="text-sm text-ink-soft leading-relaxed">
|
<p className="text-sm text-ink-soft leading-relaxed">
|
||||||
@@ -342,7 +344,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
|||||||
|
|
||||||
{/* MAINTAINER LOOP */}
|
{/* MAINTAINER LOOP */}
|
||||||
<section className="bg-paper-deep hairline-t hairline-b">
|
<section className="bg-paper-deep hairline-t hairline-b">
|
||||||
<div className="mx-auto max-w-[1400px] px-6 py-16">
|
<div className="mx-auto max-w-[1400px] px-6 py-14">
|
||||||
<div className="grid lg:grid-cols-12 gap-10 items-start">
|
<div className="grid lg:grid-cols-12 gap-10 items-start">
|
||||||
<div className="lg:col-span-5">
|
<div className="lg:col-span-5">
|
||||||
<div className="flex items-baseline gap-4 mb-4">
|
<div className="flex items-baseline gap-4 mb-4">
|
||||||
@@ -398,7 +400,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
|||||||
]
|
]
|
||||||
).map((item) => (
|
).map((item) => (
|
||||||
<div key={item.n} className="p-5">
|
<div key={item.n} className="p-5">
|
||||||
<div className="font-mono text-[0.7rem] text-indigo uppercase tracking-widest mb-2">{item.n}</div>
|
<div className={`font-mono uppercase tracking-widest mb-2 ${item.n === "01" ? "text-[0.6rem] text-indigo/60" : item.n === "04" ? "text-[0.82rem] text-indigo font-semibold" : "text-[0.7rem] text-indigo"}`}>{item.n}</div>
|
||||||
<h3 className="font-display text-lg mb-2">{item.t}</h3>
|
<h3 className="font-display text-lg mb-2">{item.t}</h3>
|
||||||
<p className={`text-sm text-ink-soft ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
|
<p className={`text-sm text-ink-soft ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
|
||||||
{item.d}
|
{item.d}
|
||||||
@@ -412,7 +414,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* HOW IT WORKS */}
|
{/* HOW IT WORKS */}
|
||||||
<section className="mx-auto max-w-[1400px] px-6 py-16">
|
<section className="mx-auto max-w-[1400px] px-6 py-12">
|
||||||
<div className="flex items-baseline gap-4 mb-8 hairline-b pb-4">
|
<div className="flex items-baseline gap-4 mb-8 hairline-b pb-4">
|
||||||
<Seal char="作" />
|
<Seal char="作" />
|
||||||
<h2 className="font-display">
|
<h2 className="font-display">
|
||||||
@@ -504,7 +506,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
|||||||
<div className="flex items-baseline gap-4 mb-5 hairline-b pb-4">
|
<div className="flex items-baseline gap-4 mb-5 hairline-b pb-4">
|
||||||
<Seal char="谢" />
|
<Seal char="谢" />
|
||||||
<div>
|
<div>
|
||||||
<div className="eyebrow mb-2">{isZh ? "v0.8.56 致谢" : "v0.8.56 credits"}</div>
|
<div className="eyebrow mb-2">{isZh ? `v${facts.version} 致谢` : `v${facts.version} credits`}</div>
|
||||||
<h2 className="font-display text-3xl">
|
<h2 className="font-display text-3xl">
|
||||||
{isZh ? "每个补丁和报告都算数" : "Every patch and report counts"}
|
{isZh ? "每个补丁和报告都算数" : "Every patch and report counts"}
|
||||||
</h2>
|
</h2>
|
||||||
@@ -556,7 +558,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
|||||||
|
|
||||||
{/* JOIN IN */}
|
{/* JOIN IN */}
|
||||||
<section className="bg-ink text-paper">
|
<section className="bg-ink text-paper">
|
||||||
<div className="mx-auto max-w-[1400px] px-6 py-16 grid lg:grid-cols-12 gap-10 items-center">
|
<div className="mx-auto max-w-[1400px] px-6 py-20 grid lg:grid-cols-12 gap-10 items-center">
|
||||||
<div className="lg:col-span-8">
|
<div className="lg:col-span-8">
|
||||||
<div className="eyebrow text-paper-deep/70 mb-3">{isZh ? "加入" : "Join in"}</div>
|
<div className="eyebrow text-paper-deep/70 mb-3">{isZh ? "加入" : "Join in"}</div>
|
||||||
<h2 className="font-display text-paper text-4xl leading-tight">
|
<h2 className="font-display text-paper text-4xl leading-tight">
|
||||||
|
|||||||
+5
-5
@@ -155,8 +155,8 @@ h3 { font-size: 1.18rem; line-height: 1.25; }
|
|||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
letter-spacing: -0.04em;
|
letter-spacing: -0.04em;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
inset 0 0 0 1px rgba(244,241,232,0.18),
|
inset 0 0 0 1px rgba(255,255,255,0.18),
|
||||||
inset 0 0 0 3px var(--ink);
|
inset 0 0 0 3px var(--ink);
|
||||||
transform: rotate(-1.5deg);
|
transform: rotate(-1.5deg);
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ h3 { font-size: 1.18rem; line-height: 1.25; }
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
inset: -1px;
|
inset: -1px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(rgba(244,241,232,0.35) 1px, transparent 1px) 0 0 / 4px 4px;
|
radial-gradient(rgba(255,255,255,0.35) 1px, transparent 1px) 0 0 / 4px 4px;
|
||||||
mix-blend-mode: screen;
|
mix-blend-mode: screen;
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@@ -175,8 +175,8 @@ h3 { font-size: 1.18rem; line-height: 1.25; }
|
|||||||
.seal-indigo {
|
.seal-indigo {
|
||||||
background: var(--indigo);
|
background: var(--indigo);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
inset 0 0 0 1px rgba(244,241,232,0.22),
|
inset 0 0 0 1px rgba(255,255,255,0.22),
|
||||||
inset 0 0 0 3px var(--indigo);
|
inset 0 0 0 3px var(--indigo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- pills / status ---------- */
|
/* ---------- pills / status ---------- */
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export function Footer({ locale = "en" }: { locale?: Locale }) {
|
|||||||
<div className="pt-2 border-t border-paper-line/20">
|
<div className="pt-2 border-t border-paper-line/20">
|
||||||
<div className="eyebrow mb-2 text-ink-mute">镜像源 / Mirror</div>
|
<div className="eyebrow mb-2 text-ink-mute">镜像源 / Mirror</div>
|
||||||
<div className="flex flex-wrap gap-3 text-xs">
|
<div className="flex flex-wrap gap-3 text-xs">
|
||||||
{GITEE_ENABLED && <a href="https://gitee.com/Hmbown/deepseek-tui" className="text-indigo hover:underline" target="_blank" rel="noopener">Gitee 镜像</a>}
|
{GITEE_ENABLED && <a href="https://gitee.com/Hmbown/CodeWhale" className="text-indigo hover:underline" target="_blank" rel="noopener">Gitee 镜像</a>}
|
||||||
<a href="https://cnb.cool/codewhale.net/codewhale" className="text-indigo hover:underline" target="_blank" rel="noopener">CNB 镜像</a>
|
<a href="https://cnb.cool/codewhale.net/codewhale" className="text-indigo hover:underline" target="_blank" rel="noopener">CNB 镜像</a>
|
||||||
<a href="https://npmmirror.com/package/codewhale" className="text-indigo hover:underline" target="_blank" rel="noopener">npmmirror</a>
|
<a href="https://npmmirror.com/package/codewhale" className="text-indigo hover:underline" target="_blank" rel="noopener">npmmirror</a>
|
||||||
<a href="https://mirrors.tuna.tsinghua.edu.cn/help/crates.io-index.html" className="text-indigo hover:underline" target="_blank" rel="noopener">Tuna crates.io</a>
|
<a href="https://mirrors.tuna.tsinghua.edu.cn/help/crates.io-index.html" className="text-indigo hover:underline" target="_blank" rel="noopener">Tuna crates.io</a>
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ export function Nav({ locale = "en" }: { locale?: Locale }) {
|
|||||||
<div className="hairline-b">
|
<div className="hairline-b">
|
||||||
<div className="mx-auto max-w-[1400px] px-6 py-1.5 flex items-center justify-between text-[0.66rem] font-mono uppercase tracking-[0.18em] text-ink-mute">
|
<div className="mx-auto max-w-[1400px] px-6 py-1.5 flex items-center justify-between text-[0.66rem] font-mono uppercase tracking-[0.18em] text-ink-mute">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<span>{isZh ? `第 ${new Date().toISOString().slice(0, 10)} 期` : `第 ${new Date().toISOString().slice(0, 10)} 期`}</span>
|
<span>{isZh ? `第 ${new Date().toISOString().slice(0, 10)} 期` : `Edition ${new Date().toISOString().slice(0, 10)}`}</span>
|
||||||
<span className="hidden sm:inline">· {isZh ? new Date().toLocaleDateString("zh-CN", { weekday: "long", month: "long", day: "numeric" }) : new Date().toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric" })}</span>
|
<span className="hidden sm:inline">· {isZh ? new Date().toLocaleDateString("zh-CN", { weekday: "long", month: "long", day: "numeric" }) : new Date().toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric" })}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<span className="hidden md:inline">codewhale.net</span>
|
<span className="hidden md:inline">codewhale.net</span>
|
||||||
<span className="inline-flex items-center gap-1.5">
|
<span className="inline-flex items-center gap-1.5">
|
||||||
<span className="w-1.5 h-1.5 bg-jade rounded-full inline-block animate-pulse" />
|
<span className="w-1.5 h-1.5 bg-jade rounded-full inline-block animate-pulse" />
|
||||||
<span>{isZh ? "API · 在线" : "API · 在线"}</span>
|
<span>{isZh ? "API · 在线" : "API · Online"}</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export function Ticker({ items }: { items: FeedItem[] }) {
|
|||||||
<div className="bg-ink text-paper px-4 py-2 flex items-center shrink-0 gap-2">
|
<div className="bg-ink text-paper px-4 py-2 flex items-center shrink-0 gap-2">
|
||||||
<span className="w-1.5 h-1.5 bg-indigo rounded-full inline-block animate-pulse" />
|
<span className="w-1.5 h-1.5 bg-indigo rounded-full inline-block animate-pulse" />
|
||||||
<span className="font-cjk text-sm font-semibold tracking-wider">实 时</span>
|
<span className="font-cjk text-sm font-semibold tracking-wider">实 时</span>
|
||||||
<span className="font-mono text-[0.7rem] uppercase tracking-widest text-paper-deep">LIVE</span>
|
<span className="font-mono text-[0.55rem] uppercase tracking-widest text-paper-deep/60 ml-1 self-end mb-0.5">LIVE</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 overflow-hidden relative">
|
<div className="flex-1 overflow-hidden relative">
|
||||||
<div className="ticker-track py-2 font-mono text-[0.78rem]">
|
<div className="ticker-track py-2 font-mono text-[0.78rem]">
|
||||||
|
|||||||
Reference in New Issue
Block a user