From 923a21c26b6c4b0fd25172c92501be883d524965 Mon Sep 17 00:00:00 2001 From: huyan Date: Sun, 23 Aug 2026 22:08:48 +0800 Subject: [PATCH 1/3] feat(landing): add open-source footer The public landing page ended without project or contribution links. Add a restrained footer and a desktop marketing-header GitHub entry. Visitors can reach the repository, issues, and contributor history. --- frontend/src/app/layout/app-header.tsx | 10 ++++ frontend/src/pages/landing/index.tsx | 74 ++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/frontend/src/app/layout/app-header.tsx b/frontend/src/app/layout/app-header.tsx index 7b55eed9..a9e3f9cd 100644 --- a/frontend/src/app/layout/app-header.tsx +++ b/frontend/src/app/layout/app-header.tsx @@ -509,6 +509,8 @@ const marketingRegisterEntry = `/?${new URLSearchParams({ returnTo: '/workspace', })}` +const githubRepository = 'https://github.com/1024XEngineer/Windup' + /** * 公开主页只换导航内容,沿用产品顶栏的布局、触控尺寸和视觉表面。 * 这样两套入口在手机上不会因为各自维护断点而逐渐错位。 @@ -570,6 +572,14 @@ function MarketingHeaderView({ session, wave, onWave }: MarketingHeaderViewProps aria-label="账号" className="relative ml-auto flex shrink-0 items-center gap-1 sm:gap-6" > + + GitHub + {session.state.status === 'booting' ? ( + +
+
+
+ + + Windup + +

+ Windup 是一个开源的 2D 角色资产工作台。 +

+

+ 查看源码、报告问题,或参与 Windup 的下一步。 +

+
+ + + + +
+ +
+

© {new Date().getFullYear()} Windup

+

2D 角色资产工作台

+
+
) } From 2dadf87cc69591cf6d27c56da8d3a4418275a5ed Mon Sep 17 00:00:00 2001 From: huyan Date: Sun, 23 Aug 2026 22:09:08 +0800 Subject: [PATCH 2/3] test(landing): cover open-source footer links The restored footer needs protection against missing or invented public links. Scope landing assertions to their navigation regions and cover footer semantics. The test now guards repository, issue, and contributor destinations. --- frontend/src/pages/landing/index.test.tsx | 32 ++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/landing/index.test.tsx b/frontend/src/pages/landing/index.test.tsx index f59f43e3..fa105157 100644 --- a/frontend/src/pages/landing/index.test.tsx +++ b/frontend/src/pages/landing/index.test.tsx @@ -73,8 +73,9 @@ describe('LandingPage', () => { ['制作流程', '#workflow'], ['资产工作台', '#workspace'], ] as const + const marketingNavigation = screen.getByRole('navigation', { name: '宣传页导航' }) for (const [name, href] of sectionLinks) { - expect(screen.getByRole('link', { name }).getAttribute('href')).toBe(href) + expect(within(marketingNavigation).getByRole('link', { name }).getAttribute('href')).toBe(href) expect(document.querySelector(href)).not.toBeNull() } expect(screen.getByRole('heading', { name: '角色做出来,还要留下来、跑起来。' })).toBeTruthy() @@ -115,4 +116,33 @@ describe('LandingPage', () => { expect(document.querySelector('img[src*="workflow-editor"]')).toBeNull() expect(document.querySelector('source[srcset*="workflow-editor"]')).toBeNull() }) + + it('在收尾插画之后提供真实的开源项目入口', async () => { + render( + + + + + , + ) + + const footer = await screen.findByRole('contentinfo') + const header = screen.getByRole('navigation', { name: '宣传页导航' }).closest('header') + + expect(header).not.toBeNull() + expect(within(header!).getByRole('link', { name: 'GitHub' }).getAttribute('href')).toBe( + 'https://github.com/1024XEngineer/Windup', + ) + expect(within(footer).getByText('Windup 是一个开源的 2D 角色资产工作台。')).toBeTruthy() + expect(within(footer).getByRole('link', { name: 'GitHub 仓库' }).getAttribute('href')).toBe( + 'https://github.com/1024XEngineer/Windup', + ) + expect(within(footer).getByRole('link', { name: 'Issues' }).getAttribute('href')).toBe( + 'https://github.com/1024XEngineer/Windup/issues', + ) + expect(within(footer).getByRole('link', { name: 'Contributors' }).getAttribute('href')).toBe( + 'https://github.com/1024XEngineer/Windup/graphs/contributors', + ) + expect(within(footer).queryByText(/隐私政策|服务条款|备案/)).toBeNull() + }) }) From 8add97a826cb9d04e2093bd3a390c784d54dde9f Mon Sep 17 00:00:00 2001 From: huyan Date: Sun, 23 Aug 2026 22:14:19 +0800 Subject: [PATCH 3/3] style(landing): format footer test Frontend CI enforces the repository oxfmt output. Apply the formatter to the scoped landing assertion. The frontend formatting check can proceed past the changed test. --- frontend/src/pages/landing/index.test.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/landing/index.test.tsx b/frontend/src/pages/landing/index.test.tsx index fa105157..986be474 100644 --- a/frontend/src/pages/landing/index.test.tsx +++ b/frontend/src/pages/landing/index.test.tsx @@ -75,7 +75,9 @@ describe('LandingPage', () => { ] as const const marketingNavigation = screen.getByRole('navigation', { name: '宣传页导航' }) for (const [name, href] of sectionLinks) { - expect(within(marketingNavigation).getByRole('link', { name }).getAttribute('href')).toBe(href) + expect(within(marketingNavigation).getByRole('link', { name }).getAttribute('href')).toBe( + href, + ) expect(document.querySelector(href)).not.toBeNull() } expect(screen.getByRole('heading', { name: '角色做出来,还要留下来、跑起来。' })).toBeTruthy()