diff --git a/site/e2e/text.spec.ts b/site/e2e/text.spec.ts
index a0dc75c..8df5c61 100644
--- a/site/e2e/text.spec.ts
+++ b/site/e2e/text.spec.ts
@@ -68,6 +68,15 @@ test.describe("English locale", () => {
await expect(lang).toHaveCSS("opacity", "1");
});
+ test("the hero links keep their icons in either language", async ({ page }) => {
+ await page.goto("/");
+ const icons = page.locator(".hero .links a > svg[aria-hidden=true]");
+ await expect(icons).toHaveCount(2);
+ await page.locator(".lang").click();
+ await expect(icons).toHaveCount(2);
+ await expect(page.locator(".hero .links a")).toHaveText(["前往下载", "源码"]);
+ });
+
test("the language button switches every text and back", async ({ page }) => {
await page.goto("/");
const lang = page.locator(".lang");
@@ -88,7 +97,7 @@ test.describe("English locale", () => {
await expect(page.locator("#download [data-t=get]")).toHaveAttribute("href", RELEASES);
await expect(page.locator(".hero .links a").last()).toHaveText("Source");
await expect(page.locator(".hero .links a").last()).toHaveAttribute("href", REPO);
- await expect(page.locator(".hero [data-t=get]")).toHaveAttribute("href", RELEASES);
+ await expect(page.locator(".hero .links a").first()).toHaveAttribute("href", RELEASES);
const files = await page.locator("a[href]").evaluateAll((as) =>
as.map((a) => (a as HTMLAnchorElement).href).filter((h) => /\.(dmg|tar\.gz|zip|exe|AppImage)$/.test(h)),
);
diff --git a/site/src/icons.ts b/site/src/icons.ts
new file mode 100644
index 0000000..7af811f
--- /dev/null
+++ b/site/src/icons.ts
@@ -0,0 +1,18 @@
+// Link icons, drawn in the link's color.
+import { said, type Key } from "./text.ts";
+
+const ICONS = {
+ download: ``,
+ gitea: ``,
+};
+
+/** A link with `icon` before its keyed text. */
+export function iconLink(icon: keyof typeof ICONS, key: Key, href: string): HTMLAnchorElement {
+ const a = document.createElement("a");
+ a.href = href;
+ a.className = "icon";
+ a.innerHTML = ICONS[icon];
+ a.firstElementChild!.setAttribute("aria-hidden", "true");
+ a.append(said("span", key));
+ return a;
+}
diff --git a/site/src/main.ts b/site/src/main.ts
index ddad563..1fd28fa 100644
--- a/site/src/main.ts
+++ b/site/src/main.ts
@@ -9,6 +9,7 @@ import { playground } from "./play.ts";
import { film } from "./film.ts";
import { said, speak, word, type Lang } from "./text.ts";
import { RELEASES, latest } from "./release.ts";
+import { iconLink } from "./icons.ts";
const REPO = "https://git.zacharyzhang.com/ZacharyZhang-NY/ElyOffice";
@@ -18,10 +19,8 @@ if (!app) throw new Error("index.html has no #app");
const hero = document.createElement("header");
const title = document.createElement("h1");
title.textContent = "Ely Office";
-const source = said("a", "source");
-source.href = REPO;
-const download = said("a", "get");
-download.href = RELEASES;
+const source = iconLink("gitea", "source", REPO);
+const download = iconLink("download", "get", RELEASES);
const links = document.createElement("div");
links.className = "links";
links.append(download, source);
diff --git a/site/src/style.css b/site/src/style.css
index 75341f3..99811d9 100644
--- a/site/src/style.css
+++ b/site/src/style.css
@@ -66,6 +66,13 @@ button:focus-visible {
gap: 1.5rem;
}
+a.icon svg {
+ height: 1em;
+ width: auto;
+ margin-inline-end: 0.35em;
+ vertical-align: -0.125em;
+}
+
.stage {
display: block;
max-width: 100%;