diff --git a/README.md b/README.md index d53d3b6..6f84398 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ pnpm add -D weapp-vite Varo -**规划中 · 跨运行时组件系统的生产底座** +**稳定版 · 跨运行时组件系统的生产底座** 为 H5 与 weapp-vite 小程序提供 registry-first primitives、组件封装、主题 token、业务 Blocks 和 Agent UI,通过 CLI 交付可编辑源码与校验能力。 @@ -70,10 +70,10 @@ pnpm add -D weapp-vite - **支持范围:** H5、WeChat、Vue 3、weapp-vite、Tailwind CSS。 ```bash -pnpm dlx @varo/cli add --target weapp-vite button input card +pnpm dlx @varo-ui/cli add --target weapp button input card ``` -[文档](https://github.com/daguanren21/Varo#readme) · [源码](https://github.com/daguanren21/Varo) · [npm](https://www.npmjs.com/package/@varo/cli) +[文档](https://daguanren21.github.io/Varo/) · [源码](https://github.com/daguanren21/Varo) · [npm](https://www.npmjs.com/package/@varo-ui/cli) ## 更多生态项目 diff --git a/apps/web/media-source/showcase/captures.json b/apps/web/media-source/showcase/captures.json index 8ae4bcf..85864d9 100644 --- a/apps/web/media-source/showcase/captures.json +++ b/apps/web/media-source/showcase/captures.json @@ -86,7 +86,7 @@ "deviceScaleFactor": 2 }, "state": "Existing AgentComponentDemo messages and waiting event snapshot; documentation viewport expanded to show the entire component.", - "attribution": "Varo AgentChat component demo, Chinese and light theme. Product remains planned on weapp.dev." + "attribution": "Varo AgentChat component demo, Chinese and light theme." } ] } diff --git a/apps/web/media-source/varo-homepage-latest.png b/apps/web/media-source/varo-homepage-latest.png new file mode 100644 index 0000000..1e85f6d Binary files /dev/null and b/apps/web/media-source/varo-homepage-latest.png differ diff --git a/apps/web/public/llms-full.txt b/apps/web/public/llms-full.txt index eafe08d..de873f2 100644 --- a/apps/web/public/llms-full.txt +++ b/apps/web/public/llms-full.txt @@ -1,6 +1,6 @@ # weapp.dev reference -weapp.dev hosts tools for real mini-app repos. weapp-tailwindcss handles styles, weapp-vite handles builds, and Varo documents planned editable component delivery boundaries. Adopt the released tools separately or together. The Chinese homepage is https://weapp.dev/ and the English homepage is https://weapp.dev/en/. The site is maintained by sonofmagic and contributors. The source repository is https://github.com/sonofmagic/weapp.dev. +weapp.dev hosts tools for real mini-app repos. weapp-tailwindcss handles styles, weapp-vite handles builds, and Varo provides Registry-first editable component delivery. Adopt the released tools separately or together. The Chinese homepage is https://weapp.dev/ and the English homepage is https://weapp.dev/en/. The site is maintained by sonofmagic and contributors. The source repository is https://github.com/sonofmagic/weapp.dev. ## weapp-tailwindcss @@ -28,9 +28,12 @@ weapp.dev hosts tools for real mini-app repos. weapp-tailwindcss handles styles, - Canonical Chinese page: https://weapp.dev/projects/varo/ - Canonical English page: https://weapp.dev/en/projects/varo/ -- Documentation and source: https://github.com/daguanren21/Varo#readme -- Purpose: Planned Registry, editable UI source, theme token, business block, and Agent UI boundaries for H5 and weapp-vite mini-programs. -- Release status: planned; package metadata, install instructions, runtime capabilities, and performance data are not published yet. +- Documentation: https://daguanren21.github.io/Varo/ +- Source: https://github.com/daguanren21/Varo +- npm: https://www.npmjs.com/package/@varo-ui/cli +- Install: `pnpm dlx @varo-ui/cli add --target weapp button input card` +- Purpose: Registry-first editable UI source, theme tokens, business Blocks, and Agent UI for H5 and Wevu mini-programs. +- Targets: Vue 3 on H5 and Wevu with weapp-vite for mini-programs. ## VPT (vite-plugin-taro) diff --git a/apps/web/public/llms.txt b/apps/web/public/llms.txt index 8fbbbb6..2611c96 100644 --- a/apps/web/public/llms.txt +++ b/apps/web/public/llms.txt @@ -1,12 +1,12 @@ # weapp.dev -> weapp.dev hosts tools for real mini-app repos: weapp-tailwindcss for styles, weapp-vite for builds, and planned Varo component delivery boundaries. You can adopt the released tools separately. +> weapp.dev hosts tools for real mini-app repos: weapp-tailwindcss for styles, weapp-vite for builds, and Varo for Registry-first component delivery. You can adopt the released tools separately. ## Official project pages - [weapp-tailwindcss](https://weapp.dev/projects/weapp-tailwindcss/): Tailwind CSS v4 generation, class transforms, and platform-aware styling for mini-apps and cross-platform frameworks. - [weapp-vite](https://weapp.dev/projects/weapp-vite/): Vite-powered development, builds, runtime tooling, and multi-platform output for mini-app projects. -- [Varo](https://weapp.dev/projects/varo/): Planned editable component delivery boundaries, primitives, business blocks, and Agent UI for H5 and weapp-vite mini-programs. +- [Varo](https://weapp.dev/projects/varo/): Registry-first editable component source, primitives, business Blocks, and Agent UI for H5 and Wevu mini-programs. - [VPT](https://weapp.dev/projects/vite-plugin-taro/): Vite 8, React 19, and Taro 4 for WeChat, Alipay, and Web apps, with state-preserving hot reload, automatic WeChat subpackages, and Tailwind CSS v4. - [English project index](https://weapp.dev/en/): English overview of the stack. - [Sponsorship and services](https://weapp.dev/pricing/): One-time sponsorship tiers with a 60/25/15 public split, plus scoped migration and training services. @@ -21,8 +21,9 @@ - [weapp-vite documentation](https://vite.weapp.dev/) - [weapp-tailwindcss on npm](https://www.npmjs.com/package/weapp-tailwindcss) - [weapp-vite on npm](https://www.npmjs.com/package/weapp-vite) -- [Varo source and documentation](https://github.com/daguanren21/Varo#readme) -- Varo package and install instructions are not published yet; see the [Varo planning page](https://weapp.dev/projects/varo/). +- [Varo source](https://github.com/daguanren21/Varo) +- [Varo documentation](https://daguanren21.github.io/Varo/) +- [@varo-ui/cli on npm](https://www.npmjs.com/package/@varo-ui/cli) - [VPT source](https://github.com/sep2/vite-plugin-taro) - [VPT documentation](https://vpt.js.org/) - [vite-plugin-taro on npm](https://www.npmjs.com/package/vite-plugin-taro) diff --git a/apps/web/public/media/projects/varo-home.avif b/apps/web/public/media/projects/varo-home.avif index 8f6402c..67684a5 100644 Binary files a/apps/web/public/media/projects/varo-home.avif and b/apps/web/public/media/projects/varo-home.avif differ diff --git a/apps/web/public/media/projects/varo-home.webp b/apps/web/public/media/projects/varo-home.webp index 76e6bc3..92c012f 100644 Binary files a/apps/web/public/media/projects/varo-home.webp and b/apps/web/public/media/projects/varo-home.webp differ diff --git a/apps/web/public/media/showcase/sources.json b/apps/web/public/media/showcase/sources.json index 8113f75..3724d05 100644 --- a/apps/web/public/media/showcase/sources.json +++ b/apps/web/public/media/showcase/sources.json @@ -188,7 +188,7 @@ "deviceScaleFactor": 2 }, "state": "Existing AgentComponentDemo messages and waiting event snapshot; documentation viewport expanded to show the entire component.", - "attribution": "Varo AgentChat component demo, Chinese and light theme. Product remains planned on weapp.dev.", + "attribution": "Varo AgentChat component demo, Chinese and light theme.", "output": { "src": "/media/showcase/varo-agent-chat-1260.webp", "avif": "/media/showcase/varo-agent-chat-1260.avif", @@ -214,11 +214,11 @@ "locales": { "zh-CN": { "alt": "Varo AgentChat 组件演示,包含对话历史、registry.inspect 工具事件、确认区域和输入框", - "caption": "Varo AgentChat 组件演示:对话、工具事件与输入区。项目仍在规划中。" + "caption": "Varo AgentChat 组件演示:对话、工具事件、审批与输入区。" }, "en": { "alt": "Varo AgentChat demo with message history, a registry.inspect tool event, approval controls and composer", - "caption": "Varo AgentChat component demo: conversation, tool events and composer. The project remains planned." + "caption": "Varo AgentChat component demo: conversation, tool events, approvals, and composer." } } } diff --git a/apps/web/public/media/sources.json b/apps/web/public/media/sources.json index af5cd5a..336e139 100644 --- a/apps/web/public/media/sources.json +++ b/apps/web/public/media/sources.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-08-27", + "generatedAt": "2026-09-16", "projectMedia": [ { "repository": "sonofmagic/weapp-tailwindcss", @@ -27,7 +27,8 @@ }, { "repository": "daguanren21/Varo", - "source": "apps/docs/public/brand-assets/varo-homepage-source.png", + "page": "https://daguanren21.github.io/Varo/", + "localSource": "../media-source/varo-homepage-latest.png", "output": "projects/varo-home", "width": 1440 }, diff --git a/apps/web/scripts/capture-showcase.mjs b/apps/web/scripts/capture-showcase.mjs index f498dcb..40d5b1d 100644 --- a/apps/web/scripts/capture-showcase.mjs +++ b/apps/web/scripts/capture-showcase.mjs @@ -133,7 +133,7 @@ try { route: '/ai/agent-chat', viewport: { width: 860, height: 1300, deviceScaleFactor: 2 }, state: 'Existing AgentComponentDemo messages and waiting event snapshot; documentation viewport expanded to show the entire component.', - attribution: 'Varo AgentChat component demo, Chinese and light theme. Product remains planned on weapp.dev.', + attribution: 'Varo AgentChat component demo, Chinese and light theme.', }) } finally { diff --git a/apps/web/scripts/generate-media.ts b/apps/web/scripts/generate-media.ts index 8a17e68..d80b1ee 100644 --- a/apps/web/scripts/generate-media.ts +++ b/apps/web/scripts/generate-media.ts @@ -1,5 +1,5 @@ import { Buffer } from 'node:buffer' -import { mkdir, writeFile } from 'node:fs/promises' +import { mkdir, readFile, writeFile } from 'node:fs/promises' import { fileURLToPath } from 'node:url' import sharp from 'sharp' @@ -32,7 +32,8 @@ const projectMedia = [ }, { repository: 'daguanren21/Varo', - source: 'apps/docs/public/brand-assets/varo-homepage-source.png', + page: 'https://daguanren21.github.io/Varo/', + localSource: '../media-source/varo-homepage-latest.png', output: 'projects/varo-home', width: 1440, }, @@ -61,7 +62,9 @@ async function downloadGitHubFile(repository: string, source: string): Promise\n 开始构建\n` }, - varo: { zh: '可编辑组件交付边界(规划中)', en: 'Editable component delivery boundary (planned)', file: 'planning.md', code: `status: planned\ninstall: to be confirmed\nruntime: to be confirmed` }, + varo: { zh: 'Registry 安装命令', en: 'Registry install command', file: 'terminal', code: `pnpm dlx @varo-ui/cli add \\\n --target weapp \\\n button input card` }, 'weapp-sqlite': { zh: '本地数据能力(规划中)', en: 'Local data capability (planned)', file: 'planning.md', code: `status: planned\napi: to be confirmed\nplatforms: to be confirmed\n\n# no production API is promised yet` }, 'vite-plugin-taro': { zh: 'Taro + Vite 迁移', en: 'Taro + Vite migration', file: 'package.json', code: `npm create vite-taro@latest my-app\n\n# keep React + Taro APIs\n# move the build pipeline to Vite` }, }[project.id] diff --git a/apps/web/src/components/ProjectSelector.astro b/apps/web/src/components/ProjectSelector.astro index e6a1e66..0856644 100644 --- a/apps/web/src/components/ProjectSelector.astro +++ b/apps/web/src/components/ProjectSelector.astro @@ -12,7 +12,7 @@ const copy = locale === 'zh-CN' ? { paths: [ { title: '新建小程序工程', body: '从现代 Vite 工程开始,再按需要叠加样式和组件。', ids: ['weapp-vite', 'weapp-tailwindcss', 'varo'] }, { title: '已有小程序项目', body: '先把样式工作流接进现有项目,不要求重写页面。', ids: ['weapp-tailwindcss'] }, - { title: '需要组件源码和业务 Blocks', body: '从 Varo 的组件与交付规划开始,评估可编辑源码和业务组合方式。', ids: ['varo'] }, + { title: '需要组件源码和业务 Blocks', body: '从 Varo Registry 安装可编辑源码,再按业务需要组合组件与 Blocks。', ids: ['varo'] }, { title: '需要本地数据', body: '评估结构化本地存储和离线能力,关注 weapp-sqlite 的规划进展。', ids: ['weapp-sqlite'] }, { title: '已有 Taro / React 项目', body: '保留 Taro 组件和 API,把开发构建链路切换到 Vite。', ids: ['vite-plugin-taro'] }, ], @@ -22,7 +22,7 @@ const copy = locale === 'zh-CN' ? { paths: [ { title: 'Starting a new mini-app', body: 'Begin with a modern Vite project, then add styling and components as needed.', ids: ['weapp-vite', 'weapp-tailwindcss', 'varo'] }, { title: 'Working in an existing mini-app', body: 'Bring the styling workflow into the current project without rewriting pages.', ids: ['weapp-tailwindcss'] }, - { title: 'Choosing component source and Blocks', body: 'Explore Varo’s component and delivery plans for editable source and business compositions.', ids: ['varo'] }, + { title: 'Choosing component source and Blocks', body: 'Install editable source from the Varo Registry, then compose components and Blocks for your product.', ids: ['varo'] }, { title: 'Planning local data', body: 'Evaluate structured storage and offline needs while weapp-sqlite is being planned.', ids: ['weapp-sqlite'] }, { title: 'Already on Taro / React', body: 'Keep Taro components and APIs while moving the development pipeline to Vite.', ids: ['vite-plugin-taro'] }, ], diff --git a/apps/web/src/content.test.ts b/apps/web/src/content.test.ts index 6c0bde5..ea31f77 100644 --- a/apps/web/src/content.test.ts +++ b/apps/web/src/content.test.ts @@ -13,7 +13,7 @@ describe('project definitions', () => { 'weapp-vite': 'https://vite.weapp.dev/', 'vite-plugin-taro': 'https://vpt.js.org/', 'weapp-sqlite': 'https://github.com/weapp-sqlite/weapp-sqlite#readme', - '@varo/cli': 'https://github.com/daguanren21/Varo#readme', + '@varo-ui/cli': 'https://daguanren21.github.io/Varo/', } it('provides complete localized content for every project', () => { @@ -64,12 +64,15 @@ describe('project definitions', () => { } }) - it('uses explicit placeholders for the planned Varo release', () => { + it('publishes the Varo release and package actions', () => { expect(varo).toMatchObject({ - status: 'planned', - packageName: '@varo/cli', + status: 'stable', + maturity: 'stable', + packageName: '@varo-ui/cli', github: 'daguanren21/Varo', - docsUrl: 'https://github.com/daguanren21/Varo#readme', + docsUrl: 'https://daguanren21.github.io/Varo/', + npmUrl: 'https://www.npmjs.com/package/@varo-ui/cli', + installCommand: 'pnpm dlx @varo-ui/cli add --target weapp button input card', }) }) @@ -87,6 +90,7 @@ describe('project definitions', () => { 'weapp-vite': 'https://www.npmjs.com/package/weapp-vite', 'weapp-tailwindcss': 'https://www.npmjs.com/package/weapp-tailwindcss', 'vite-plugin-taro': 'https://www.npmjs.com/package/vite-plugin-taro', + '@varo-ui/cli': 'https://www.npmjs.com/package/@varo-ui/cli', } for (const project of projects) { diff --git a/apps/web/src/content/projects/varo.json b/apps/web/src/content/projects/varo.json index 97f88db..4d88eaa 100644 --- a/apps/web/src/content/projects/varo.json +++ b/apps/web/src/content/projects/varo.json @@ -1,9 +1,11 @@ { "order": 3, - "status": "planned", - "packageName": "@varo/cli", + "status": "stable", + "packageName": "@varo-ui/cli", "github": "daguanren21/Varo", - "docsUrl": "https://github.com/daguanren21/Varo#readme", + "docsUrl": "https://daguanren21.github.io/Varo/", + "npmUrl": "https://www.npmjs.com/package/@varo-ui/cli", + "license": "https://opensource.org/license/mit", "maintainer": "daguanren21 and contributors", "keywords": [ "Vue 3", @@ -14,11 +16,12 @@ "Agent UI", "Blocks" ], + "installCommand": "pnpm dlx @varo-ui/cli add --target weapp button input card", "futureDocsPath": "/docs/varo/", "logo": "/brands/varo.svg", "accent": "#07c160", "role": "Components", - "maturity": "planned", + "maturity": "stable", "runtime": [ "Vue 3", "H5", @@ -28,7 +31,7 @@ "weapp-tailwindcss", "weapp-sqlite" ], - "dataCompleteness": "partial", + "dataCompleteness": "complete", "platforms": [ "H5", "WeChat", @@ -44,12 +47,12 @@ "height": 990, "locales": { "zh-CN": { - "alt": "Varo 文档首页展示跨运行时组件系统能力", - "caption": "Varo 正在规划 primitives、可复制源码与交付校验如何服务 H5 和小程序组件系统。" + "alt": "Varo Registry-first 文档首页展示 H5 与小程序双端安装路径", + "caption": "Varo 文档首页展示 Registry-first 双端组件交付路径。" }, "en": { - "alt": "Varo documentation home showing the cross-runtime component system", - "caption": "Varo is planning how primitives, editable source, and delivery checks should serve H5 and mini-program component systems." + "alt": "Varo Registry-first documentation home showing H5 and mini-program installation paths", + "caption": "The Varo documentation home presents its Registry-first component delivery paths for both runtimes." } } }, @@ -61,11 +64,11 @@ "locales": { "zh-CN": { "alt": "Varo Agent UI 完整对话与工具界面", - "caption": "Agent UI 与 Agent Chat Block 的交互协议仍在规划中。" + "caption": "Agent UI 与 Agent Chat Block 提供对话、工具调用与审批交互。" }, "en": { "alt": "Varo Agent UI conversation and tool interface", - "caption": "The Agent UI and Agent Chat Block interaction contract is still planned." + "caption": "Agent UI and the Agent Chat Block provide conversation, tool-call, and approval interactions." } } } @@ -73,55 +76,55 @@ "locales": { "zh-CN": { "name": "Varo", - "tagline": "双端组件交付规划", - "description": "Varo 正在整理 H5 与小程序的可编辑组件交付边界,安装方式、运行时范围和稳定资料确认后再公开。", + "tagline": "双端移动 UI Registry", + "description": "Varo 通过 Registry 向 H5 与 Wevu 小程序交付可编辑组件源码、业务 Blocks 与 Agent UI,并保留各端原生渲染。", "audience": "需要在 H5 与小程序之间共享交互语义、组件源码和业务 Blocks 的 Vue 3 团队。", "useCases": [ - "评估可编辑组件源码的交付边界", - "规划双端业务 Blocks 与 Agent UI 的组合方式", - "确认 primitives 与主题 token 的公开契约" + "从 Registry 安装可编辑的 H5 或小程序组件源码", + "复用双端业务 Blocks 与 Agent UI", + "基于 headless primitives 和主题 token 构建设计系统" ], "capabilities": [ - "可编辑组件源码(规划中)", - "双端运行时边界(待确认)", - "Registry 与 Agent UI 契约(待确认)", - "稳定版本与安装路径(待公开)" + "56 个 H5 Registry 组件族", + "45 个小程序 Registry 组件族", + "Registry 与 Agent UI", + "Vue 3 + Wevu 双端原生渲染" ], "faqs": [ { "question": "Varo 和传统 npm 组件库有什么不同?", - "answer": "Varo 计划提供可复制、修改并归业务项目所有的组件与 Blocks 源码;具体交付方式仍在确认。" + "answer": "Varo 默认通过 Registry 把组件与 Blocks 源码安装到业务项目中,团队可以直接修改并拥有这些源码。" }, { - "question": "Varo 当前支持哪些运行时?", - "answer": "目标运行时包含 H5 与 weapp-vite,但公开范围、组件数量和稳定 API 仍待确认。" + "question": "Varo 支持哪些运行时?", + "answer": "H5 使用 Vue 3,小程序使用 Wevu 与 weapp-vite;两端共享类型、纯函数和 headless primitives。" } ] }, "en": { "name": "Varo", - "tagline": "A planned boundary for dual-runtime component delivery", - "description": "Varo is defining an editable component delivery boundary for H5 and mini-apps. Installation, runtime scope, and stable reference material will be published after confirmation.", + "tagline": "Registry-first mobile UI for two runtimes", + "description": "Varo delivers editable component source, business Blocks, and Agent UI to H5 and Wevu mini-program projects through its Registry while preserving native rendering on each target.", "audience": "Vue 3 teams that need shared interaction semantics, component source, and business blocks across H5 and mini-program products.", "useCases": [ - "Evaluate the boundary for editable component source", - "Plan dual-target business blocks and Agent UI composition", - "Confirm the public contract for primitives and theme tokens" + "Install editable H5 or mini-program component source from the Registry", + "Reuse dual-target business Blocks and Agent UI", + "Build a design system on headless primitives and theme tokens" ], "capabilities": [ - "Editable component source (planned)", - "Dual-runtime boundaries (to be confirmed)", - "Registry and Agent UI contract (to be confirmed)", - "Stable release and install path (not published yet)" + "56 H5 Registry component families", + "45 mini-program Registry component families", + "Registry and Agent UI", + "Native Vue 3 and Wevu rendering" ], "faqs": [ { "question": "How is Varo different from a traditional npm UI library?", - "answer": "Varo plans to deliver component and block source that teams can copy, modify, and own; the delivery method is still being confirmed." + "answer": "Varo uses its Registry to install component and Block source into the product repository by default, so teams can modify and own that source." }, { - "question": "Which runtimes does Varo support today?", - "answer": "The target runtimes include H5 and weapp-vite, but public scope, component counts, and stable APIs are still being confirmed." + "question": "Which runtimes does Varo support?", + "answer": "H5 uses Vue 3, while mini-program projects use Wevu and weapp-vite. The targets share types, pure functions, and headless primitives." } ] } diff --git a/apps/web/src/content/showcases/varo.json b/apps/web/src/content/showcases/varo.json index fdd2dcb..94b39a7 100644 --- a/apps/web/src/content/showcases/varo.json +++ b/apps/web/src/content/showcases/varo.json @@ -25,11 +25,11 @@ "locales": { "zh-CN": { "alt": "Varo AgentChat 组件演示,包含对话历史、registry.inspect 工具事件、确认区域和输入框", - "caption": "Varo AgentChat 组件演示:对话、工具事件与输入区。项目仍在规划中。" + "caption": "Varo AgentChat 组件演示:对话、工具事件、审批与输入区。" }, "en": { "alt": "Varo AgentChat demo with message history, a registry.inspect tool event, approval controls and composer", - "caption": "Varo AgentChat component demo: conversation, tool events and composer. The project remains planned." + "caption": "Varo AgentChat component demo: conversation, tool events, approvals, and composer." } } } diff --git a/apps/web/src/data/project-metrics.fallback.json b/apps/web/src/data/project-metrics.fallback.json index 434c452..969adb3 100644 --- a/apps/web/src/data/project-metrics.fallback.json +++ b/apps/web/src/data/project-metrics.fallback.json @@ -14,11 +14,11 @@ "fetchedAt": "2026-08-26T00:00:00.000Z" }, "varo": { - "version": "0.0.1", - "releasedAt": "2026-08-26T00:00:00.000Z", - "stars": 0, - "weeklyDownloads": 0, - "fetchedAt": "2026-08-26T00:00:00.000Z" + "version": "2.1.0", + "releasedAt": "2026-09-13T15:45:51.579Z", + "stars": 2, + "weeklyDownloads": 195, + "fetchedAt": "2026-09-16T00:00:00.000Z" }, "vite-plugin-taro": { "version": "0.7.1", diff --git a/apps/web/src/i18n/home/en.ts b/apps/web/src/i18n/home/en.ts index cd1851e..65b90f4 100644 --- a/apps/web/src/i18n/home/en.ts +++ b/apps/web/src/i18n/home/en.ts @@ -14,7 +14,7 @@ export default { items: [ { title: 'Author', body: 'Keep writing native mini-app pages, Vue SFCs, or your current cross-platform setup. Do not reshuffle page boundaries just for tooling.' }, { title: 'Build', body: 'Hand classes and styles to weapp-tailwindcss. Hand deps, routes, and single-target multi-platform builds to weapp-vite.' }, - { title: 'Compose', body: 'When you need component delivery, evaluate Varo’s editable-source boundary; installation guidance will follow a stable release.' }, + { title: 'Compose', body: 'When you need component delivery, use the Varo Registry to install editable source for each target, then add business Blocks and Agent UI.' }, { title: 'Store', body: 'When you need structured local data, follow the runtime boundaries and migration plan for weapp-sqlite.' }, { title: 'Migrate', body: 'Existing Taro / React projects can move their development and build pipeline to Vite with VPT.' }, ], @@ -33,7 +33,7 @@ export default { planned: 'Planned', }, readinessTitle: 'No public metrics yet', - readinessBody: 'The component layer is still in progress. We will not show downloads or stars before a stable release, so the page does not pretend with zeros.', + readinessBody: 'Downloads and stars stay hidden until a stable release, rather than presenting zeros as proof.', proof: { styleLabel: 'Default style markup', styleFile: 'button.wxml', @@ -66,7 +66,7 @@ export default { }, { title: 'Components · Varo', - owns: 'Editable components, Blocks, and registry delivery boundaries (planned).', + owns: 'Editable components, Blocks, and Registry delivery boundaries.', notOwns: 'Your project scaffold, or forcing a rewrite of existing pages.', }, { diff --git a/apps/web/src/i18n/home/zh-CN.ts b/apps/web/src/i18n/home/zh-CN.ts index 6db98ac..ab50453 100644 --- a/apps/web/src/i18n/home/zh-CN.ts +++ b/apps/web/src/i18n/home/zh-CN.ts @@ -14,7 +14,7 @@ export default { items: [ { title: '编写', body: '继续写原生小程序、Vue SFC,或你现在的跨端框架。页面边界不用为了工具先改一轮。' }, { title: '构建', body: '类名和样式交给 weapp-tailwindcss;依赖、路由和多平台单目标构建交给 weapp-vite。' }, - { title: '组装', body: '需要组件交付时,先评估 Varo 的可编辑源码与组件边界;项目稳定后再公布安装路径。' }, + { title: '组装', body: '需要组件交付时,用 Varo Registry 按目标安装可编辑源码,再叠加业务 Blocks 与 Agent UI。' }, { title: '存储', body: '需要本地结构化数据时,关注 weapp-sqlite 的运行时边界和迁移计划。' }, { title: '迁移', body: '已有 Taro / React 项目可以通过 VPT 把开发构建链路切到 Vite。' }, ], @@ -33,7 +33,7 @@ export default { planned: '规划中', }, readinessTitle: '现在还没公开指标', - readinessBody: '组件层还在做。稳定发布前不展示下载和 Stars,免得页面上挂两个 0 装样子。', + readinessBody: '项目稳定发布前不展示下载和 Stars,避免用两个 0 充当可信度。', proof: { styleLabel: '默认样式写法', styleFile: 'button.wxml', @@ -66,7 +66,7 @@ export default { }, { title: '组件 · Varo', - owns: '可编辑组件、Blocks 与 Registry 交付边界(规划中)。', + owns: '可编辑组件、Blocks 与 Registry 交付边界。', notOwns: '整个工程脚手架,也不强迫你改掉现有页面写法。', }, { diff --git a/apps/web/src/i18n/ui.ts b/apps/web/src/i18n/ui.ts index 217a3f9..b6e7e9c 100644 --- a/apps/web/src/i18n/ui.ts +++ b/apps/web/src/i18n/ui.ts @@ -158,7 +158,7 @@ export const siteCopy = { sponsorEmpty: '目前没有可公开展示的记录。', sponsorDisplay: '查看 GitHub link', roadmapTitle: '建设中的能力', - roadmapDescription: '云构建、官方模板和私有组件仓库会在具备稳定交付链路后再开放。Varo 仍是规划中的组件库存,不按 GA 日期收费。', + roadmapDescription: 'Varo 公共 Registry 已发布;云构建、官方模板和私有组件仓库仍会在具备稳定交付链路后再开放。', templatesTitle: '第一批官方模板', templatesDescription: '这是建设方向,不代表模板已经上线或可以购买。未来计划邀请制上架,先做能过审、能换皮的场景。', templates: [ @@ -413,7 +413,7 @@ export const siteCopy = { sponsorEmpty: 'No public records are available yet.', sponsorDisplay: 'View GitHub link', roadmapTitle: 'Capabilities in development', - roadmapDescription: 'Cloud builds, official templates, and private component registries will open after a stable delivery path exists. Varo remains planned component inventory and is not charged against a GA date.', + roadmapDescription: 'The public Varo Registry is available. Cloud builds, official templates, and private component registries will open after a stable delivery path exists.', templatesTitle: 'The first official templates', templatesDescription: 'This is a direction, not a live catalog or purchasable inventory. Future publishing will be invite-only and focused on reviewable, rebrandable scenarios.', templates: [ diff --git a/apps/web/src/lib/seo.test.ts b/apps/web/src/lib/seo.test.ts index f320228..166b16d 100644 --- a/apps/web/src/lib/seo.test.ts +++ b/apps/web/src/lib/seo.test.ts @@ -28,13 +28,13 @@ describe('SEO helpers', () => { expect(JSON.parse(serializeJsonLd(entity))).toEqual(entity) }) - it('does not publish release or package claims for planned projects', () => { + it('publishes release and package claims for Varo', () => { const project = { id: 'varo', data: varo as unknown as ProjectDefinition } const entity = projectSchema('en', project, fallbackMetrics.varo) - expect(entity).not.toHaveProperty('version') - expect(entity).not.toHaveProperty('dateModified') - expect(entity).not.toHaveProperty('downloadUrl') - expect(entity.sameAs).not.toContain('https://www.npmjs.com/package/@varo/cli') + expect(entity.version).toBe('2.1.0') + expect(entity.dateModified).toBe('2026-09-13T15:45:51.579Z') + expect(entity.downloadUrl).toBe('https://www.npmjs.com/package/@varo-ui/cli') + expect(entity.sameAs).toContain('https://www.npmjs.com/package/@varo-ui/cli') }) it('keeps the planned weapp-sqlite schema free of unconfirmed runtime claims', () => { diff --git a/apps/web/src/lib/toolchain.test.ts b/apps/web/src/lib/toolchain.test.ts index e887d3a..cb3f55f 100644 --- a/apps/web/src/lib/toolchain.test.ts +++ b/apps/web/src/lib/toolchain.test.ts @@ -56,7 +56,7 @@ describe('toolchain project ordering', () => { id: ['weapp-vite', 'weapp-tailwindcss', 'varo', 'weapp-sqlite', 'vite-plugin-taro'][index], data: projectDefinitionSchema.parse(data), })) as unknown as ProjectEntry[] - projects[2].data.dataCompleteness = 'complete' + projects[3].data.dataCompleteness = 'complete' expect(() => validateToolchainCatalog(projects)).toThrow('Planned project cannot claim complete data') }) @@ -86,9 +86,9 @@ describe('toolchain project ordering', () => { id: ['weapp-vite', 'weapp-tailwindcss', 'varo', 'weapp-sqlite', 'vite-plugin-taro'][index], data: projectDefinitionSchema.parse(data), })) as unknown as ProjectEntry[] - projects[2].data.installCommand = 'pnpm dlx @varo/cli' + projects[3].data.installCommand = 'pnpm add weapp-sqlite' expect(() => validateToolchainCatalog(projects)).toThrow('Planned project cannot publish package actions') - projects[2].data.installCommand = undefined + projects[3].data.installCommand = undefined projects[0].data.npmUrl = undefined expect(() => validateToolchainCatalog(projects)).toThrow('Active project is missing package actions') }) diff --git a/apps/web/src/styles/global.css b/apps/web/src/styles/global.css index 3a73c1c..d80045b 100644 --- a/apps/web/src/styles/global.css +++ b/apps/web/src/styles/global.css @@ -224,13 +224,60 @@ box-shadow: var(--shadow-panel); isolation: isolate; } -.home-hero-stage::after { position: absolute; inset: 0; z-index: 1; pointer-events: none; content: ''; background: linear-gradient(120deg, rgb(255 255 255 / 18%), transparent 42%, rgb(14 121 88 / 12%)); mix-blend-mode: screen; } -.home-hero-stage-grid, .home-hero-stage-scan { position: absolute; z-index: 2; pointer-events: none; } -.home-hero-stage-grid { inset: 0; opacity: 0.28; background-image: linear-gradient(rgb(14 121 88 / 16%) 1px, transparent 1px), linear-gradient(90deg, rgb(14 121 88 / 16%) 1px, transparent 1px); background-size: 42px 42px; } -.home-hero-stage-scan { top: -25%; right: 0; left: 0; height: 30%; opacity: 0.5; background: linear-gradient(180deg, transparent, rgb(105 199 165 / 22%), transparent); } -.home-hero-stage-marker, .home-hero-stage-readout { position: absolute; z-index: 3; color: var(--accent-contrast); font: 650 0.65rem/1.2 var(--font-mono); letter-spacing: 0.08em; background: rgb(7 19 14 / 72%); border: 1px solid rgb(105 199 165 / 44%); backdrop-filter: blur(8px); } -.home-hero-stage-marker { top: 1rem; left: 1rem; padding: 0.45rem 0.6rem; } -.home-hero-stage-readout { right: 1rem; bottom: 1rem; display: flex; gap: 0.6rem; padding: 0.45rem 0.6rem; } +.home-hero-stage::after { + position: absolute; + inset: 0; + z-index: 1; + pointer-events: none; + content: ''; + background: linear-gradient(120deg, rgb(255 255 255 / 18%), transparent 42%, rgb(14 121 88 / 12%)); + mix-blend-mode: screen; +} +.home-hero-stage-grid, +.home-hero-stage-scan { + position: absolute; + z-index: 2; + pointer-events: none; +} +.home-hero-stage-grid { + inset: 0; + opacity: 0.28; + background-image: + linear-gradient(rgb(14 121 88 / 16%) 1px, transparent 1px), + linear-gradient(90deg, rgb(14 121 88 / 16%) 1px, transparent 1px); + background-size: 42px 42px; +} +.home-hero-stage-scan { + top: -25%; + right: 0; + left: 0; + height: 30%; + opacity: 0.5; + background: linear-gradient(180deg, transparent, rgb(105 199 165 / 22%), transparent); +} +.home-hero-stage-marker, +.home-hero-stage-readout { + position: absolute; + z-index: 3; + color: var(--accent-contrast); + font: 650 0.65rem/1.2 var(--font-mono); + letter-spacing: 0.08em; + background: rgb(7 19 14 / 72%); + border: 1px solid rgb(105 199 165 / 44%); + backdrop-filter: blur(8px); +} +.home-hero-stage-marker { + top: 1rem; + left: 1rem; + padding: 0.45rem 0.6rem; +} +.home-hero-stage-readout { + right: 1rem; + bottom: 1rem; + display: flex; + gap: 0.6rem; + padding: 0.45rem 0.6rem; +} .home-hero-stage picture, .home-hero-stage img { width: 100%; @@ -650,28 +697,56 @@ [data-hero-enter] { animation: hero-enter 600ms var(--enter-delay, 0ms) cubic-bezier(0.16, 1, 0.3, 1) both; } -[data-project-visual] img { - filter: saturate(0.92) contrast(1.03); - transition: filter 260ms ease, transform 260ms ease; -} -[data-project-visual]:hover img, -[data-project-visual]:focus-within img { - filter: saturate(1) contrast(1.06); -} - [data-project-visual] img { transition: transform 260ms ease, filter 260ms ease; } + [data-project-visual] img { + filter: saturate(0.92) contrast(1.03); + transition: + filter 260ms ease, + transform 260ms ease; + } + [data-project-visual]:hover img, + [data-project-visual]:focus-within img { + filter: saturate(1) contrast(1.06); + } + [data-project-visual] img { + transition: + transform 260ms ease, + filter 260ms ease; + } [data-project-row]:focus-within [data-project-visual] img { transform: scale(1.012); } - .home-hero-stage-scan { animation: hero-scan 5.5s ease-in-out infinite; } - .home-hero-stage-asset { transition: transform 500ms ease, filter 500ms ease; } - .home-hero-stage:hover .home-hero-stage-asset { transform: scale(1.025); filter: saturate(1) contrast(1.04); } + .home-hero-stage-scan { + animation: hero-scan 5.5s ease-in-out infinite; + } + .home-hero-stage-asset { + transition: + transform 500ms ease, + filter 500ms ease; + } + .home-hero-stage:hover .home-hero-stage-asset { + transform: scale(1.025); + filter: saturate(1) contrast(1.04); + } @media (hover: hover) { [data-project-row]:hover [data-project-visual] img { transform: scale(1.012); } } } -@keyframes hero-scan { 0%, 100% { transform: translateY(-15%); opacity: 0; } 20%, 80% { opacity: 0.5; } 50% { transform: translateY(285%); } } +@keyframes hero-scan { + 0%, + 100% { + transform: translateY(-15%); + opacity: 0; + } + 20%, + 80% { + opacity: 0.5; + } + 50% { + transform: translateY(285%); + } +} @media (prefers-reduced-motion: reduce) { *, *::before, diff --git a/apps/web/tests/e2e/projects.spec.ts b/apps/web/tests/e2e/projects.spec.ts index f674d64..d52e487 100644 --- a/apps/web/tests/e2e/projects.spec.ts +++ b/apps/web/tests/e2e/projects.spec.ts @@ -22,12 +22,12 @@ for (const prefix of ['', '/en']) { const links = page.locator('.toolchain-map-list li a') await expect(links).toHaveCount(5) const statusLabels = prefix ? { stable: 'Stable', planned: 'Planned' } : { stable: '稳定', planned: '规划中' } - for (const id of ['weapp-vite', 'weapp-tailwindcss', 'vite-plugin-taro']) { + for (const id of ['weapp-vite', 'weapp-tailwindcss', 'varo', 'vite-plugin-taro']) { const node = page.locator('.toolchain-map-list li').filter({ has: page.locator(`a[href="${prefix}/projects/${id}/"]`) }) await expect(node.locator('.toolchain-status')).toHaveText(statusLabels.stable) await expect(node.locator('.toolchain-status')).toHaveAttribute('aria-label', prefix ? 'Project status: Stable' : '项目状态: 稳定') } - for (const id of ['varo', 'weapp-sqlite']) { + for (const id of ['weapp-sqlite']) { const node = page.locator('.toolchain-map-list li').filter({ has: page.locator(`a[href="${prefix}/projects/${id}/"]`) }) await expect(node.locator('.toolchain-status')).toHaveText(statusLabels.planned) await expect(node.locator('.toolchain-status')).toHaveAttribute('aria-label', prefix ? 'Project status: Planned' : '项目状态: 规划中') @@ -189,27 +189,6 @@ for (const prefix of ['', '/en']) { await expect(heroVisual).toHaveAttribute('decoding', 'async') }) - test(`offers five adoption paths and their documentation on ${prefix}/`, async ({ page }) => { - await page.goto(`${prefix}/`) - const paths = page.locator('.project-selector-list article') - await expect(paths).toHaveCount(5) - for (const [index, slug] of ['weapp-vite', 'weapp-tailwindcss', 'varo', 'weapp-sqlite', 'vite-plugin-taro'].entries()) { - const path = paths.nth(index) - await expect(path).toHaveAttribute('aria-labelledby', `path-title-${index}`) - await expect(path).toHaveAttribute('aria-describedby', ['varo', 'weapp-sqlite'].includes(slug) ? `path-description-${index} selector-status-${index}` : `path-description-${index} selector-command-${index}`) - await expect(path.locator('.project-selector-actions a').first()).toHaveAttribute('href', `${prefix}/projects/${slug}/`) - await expect(path.locator('.project-selector-actions a').last()).toHaveAttribute('href', /^https:\/\//) - if (['varo', 'weapp-sqlite'].includes(slug)) { - await expect(path.locator('code')).toHaveCount(0) - await expect(path.locator('.project-selector-planned')).toContainText(zh ? '规划中' : 'planned') - await expect(path.locator('.project-selector-planned')).toHaveAttribute('aria-label', zh ? '项目状态:规划中' : 'Project status: Planned') - } - else { - await expect(path.locator('code')).not.toBeEmpty() - } - } - }) - test(`publishes all five projects in the localized ItemList schema on ${prefix}/projects/`, async ({ page }) => { await page.goto(`${prefix}/projects/`) const schema = await page.locator('script[type="application/ld+json"]').evaluateAll(scripts => scripts.map(script => JSON.parse(script.textContent ?? '{}')).find(value => value['@type'] === 'ItemList')) @@ -236,7 +215,7 @@ for (const prefix of ['', '/en']) { await page.emulateMedia({ colorScheme: theme, reducedMotion: 'reduce' }) for (const slug of ['weapp-vite', 'weapp-tailwindcss', 'varo', 'weapp-sqlite', 'vite-plugin-taro']) { await page.goto(`${prefix}/projects/${slug}/`) - await expect(page.getByRole('link', { name: prefix ? 'Back to projects' : '返回项目列表', exact: true })).toHaveAttribute('href', `${prefix}/projects/`) + await expect(page.getByRole('link', { name: prefix ? 'Back to the stack' : '返回工具栈', exact: true })).toHaveAttribute('href', `${prefix}/projects/`) await expect(page.locator('section[aria-labelledby="project-title"]')).toHaveCount(1) await expect(page.locator('section[aria-labelledby="project-faq-title"]')).toHaveCount(1) await expect(page.locator('section[aria-labelledby="project-future-docs-title"]')).toHaveCount(1) @@ -270,11 +249,11 @@ test.describe('project catalog without JavaScript', () => { await page.locator('[data-project-card][data-role="data"] .projects-index-actions a').last().click() await expect(page).toHaveURL(`${prefix}/projects/weapp-sqlite/`) await expect(page.getByRole('heading', { level: 1 })).toHaveText('weapp-sqlite') - await expect(page.getByRole('region', { name: prefix ? 'Integration status' : '接入状态', exact: true })).toBeVisible() + await expect(page.getByRole('region', { name: prefix ? 'Project data' : '项目数据', exact: true })).toBeVisible() await expect(page.locator('main figure')).toHaveCount(0) await expect(page.locator('.project-proof-panel')).toBeVisible() await expect(page.locator('.roadmap-strip')).toBeVisible() - const back = page.getByRole('link', { name: prefix ? 'Back to projects' : '返回项目列表', exact: true }) + const back = page.getByRole('link', { name: prefix ? 'Back to the stack' : '返回工具栈', exact: true }) await back.focus() await page.keyboard.press('Enter') await expect(page).toHaveURL(`${prefix}/projects/`) @@ -290,10 +269,10 @@ for (const width of [1440, 768, 390]) { await page.emulateMedia({ colorScheme: theme, reducedMotion: 'reduce' }) await page.goto('/en/projects/weapp-sqlite/') await expect(page.getByRole('heading', { level: 1, name: 'weapp-sqlite' })).toBeVisible() - await expect(page.getByRole('region', { name: 'Integration status', exact: true })).toBeInViewport() + await expect(page.getByRole('region', { name: 'Project data', exact: true })).toBeVisible() await expect(page.locator('main figure')).toHaveCount(0) expect(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth)).toBe(false) - const readiness = page.getByText('Planned projects omit downloads and stars. Public numbers return after a stable release.', { exact: true }) + const readiness = page.getByText('Stability and release status follow the project repository and version data.', { exact: true }) await expect(readiness).toHaveCount(1) await page.screenshot({ path: testInfo.outputPath('planned-project-detail.png') }) }) @@ -307,10 +286,6 @@ for (const width of [1440, 768, 390]) { const results = await new AxeBuilder({ page }).include('main').analyze() expect(results.violations).toEqual([]) await page.screenshot({ path: testInfo.outputPath('project-catalog.png'), fullPage: true }) - await page.goto('/en/') - await page.locator('.project-selector').scrollIntoViewIfNeeded() - expect(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth)).toBe(false) - await page.locator('.project-selector').screenshot({ path: testInfo.outputPath('project-paths.png'), style: '[data-site-header], body > a[href="#main-content"] { visibility: hidden !important; }' }) }) } } diff --git a/apps/web/tests/e2e/site.spec.ts b/apps/web/tests/e2e/site.spec.ts index 7bd43d7..4d75d96 100644 --- a/apps/web/tests/e2e/site.spec.ts +++ b/apps/web/tests/e2e/site.spec.ts @@ -5,7 +5,7 @@ import tailwindProject from '../../src/content/projects/weapp-tailwindcss.json' import viteProject from '../../src/content/projects/weapp-vite.json' with { type: 'json' } import { siteCopy } from '../../src/i18n/ui' -const projectDefinitions = [tailwindProject, viteProject, varoProject] +const projectDefinitions = [viteProject, tailwindProject, varoProject] const retiredVisuals = 'canvas, [data-shader-canvas], [data-shader], [data-shader-frame], [data-webgl-fallback], [data-art], .project-art, [class^="art-"], [class*=" art-"]' async function expectHomeVisuals(page: import('@playwright/test').Page, locale: 'zh-CN' | 'en') { @@ -77,29 +77,31 @@ test('renders the bilingual ecosystem home with valid metadata', async ({ page } const docsLinks = page.locator('#projects').getByRole('link', { name: '阅读文档' }) await expect(docsLinks).toHaveCount(3) await expect(docsLinks.evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([ - 'https://tw.weapp.dev/', 'https://vite.weapp.dev/', - 'https://github.com/daguanren21/Varo#readme', + 'https://tw.weapp.dev/', + 'https://daguanren21.github.io/Varo/', ]) const projectHomeLinks = page.locator('.home-project-rail a') await expect(projectHomeLinks.evaluateAll(links => links.map(link => ({ href: link.getAttribute('href'), target: link.getAttribute('target'), rel: link.getAttribute('rel') })))).resolves.toEqual([ - { href: 'https://tw.weapp.dev/', target: '_blank', rel: 'noreferrer' }, - { href: 'https://vite.weapp.dev/', target: '_blank', rel: 'noreferrer' }, - { href: 'https://github.com/daguanren21/Varo#readme', target: '_blank', rel: 'noreferrer' }, + { href: 'https://vite.weapp.dev/', target: '_blank', rel: 'noopener noreferrer' }, + { href: 'https://tw.weapp.dev/', target: '_blank', rel: 'noopener noreferrer' }, + { href: 'https://daguanren21.github.io/Varo/', target: '_blank', rel: 'noopener noreferrer' }, + { href: 'https://github.com/weapp-sqlite/weapp-sqlite#readme', target: '_blank', rel: 'noopener noreferrer' }, + { href: 'https://vpt.js.org/', target: '_blank', rel: 'noopener noreferrer' }, ]) await expect(page.locator('.home-project-visual-link').evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([ - 'https://tw.weapp.dev/', 'https://vite.weapp.dev/', - 'https://github.com/daguanren21/Varo#readme', + 'https://tw.weapp.dev/', + 'https://daguanren21.github.io/Varo/', ]) await expect(page.locator('.home-project-title-link').evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([ - 'https://tw.weapp.dev/', 'https://vite.weapp.dev/', - 'https://github.com/daguanren21/Varo#readme', + 'https://tw.weapp.dev/', + 'https://daguanren21.github.io/Varo/', ]) await expect(page.locator('#projects a[data-analytics-event="select_project"]').evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([ - '/projects/weapp-tailwindcss/', '/projects/weapp-vite/', + '/projects/weapp-tailwindcss/', '/projects/varo/', ]) @@ -110,14 +112,16 @@ test('renders the bilingual ecosystem home with valid metadata', async ({ page } await expect(page.locator('link[rel="canonical"]')).toHaveAttribute('href', 'https://weapp.dev/en/') await expect(page.locator('link[hreflang="zh-CN"]')).toHaveAttribute('href', 'https://weapp.dev/') await expect(page.locator('#projects a[data-analytics-event="select_project"]').evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([ - '/en/projects/weapp-tailwindcss/', '/en/projects/weapp-vite/', + '/en/projects/weapp-tailwindcss/', '/en/projects/varo/', ]) await expect(page.locator('.home-project-rail a').evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([ - 'https://tw.weapp.dev/', 'https://vite.weapp.dev/', - 'https://github.com/daguanren21/Varo#readme', + 'https://tw.weapp.dev/', + 'https://daguanren21.github.io/Varo/', + 'https://github.com/weapp-sqlite/weapp-sqlite#readme', + 'https://vpt.js.org/', ]) }) @@ -223,7 +227,7 @@ test('project detail exposes docs, source, metrics, and future path', async ({ p await expect(page.getByText('/docs/weapp-vite/')).toBeVisible() await expect(page.getByText('GitHub Stars')).toBeVisible() await expect(page.getByRole('heading', { name: '常见问题' })).toBeVisible() - await expect(page.locator('pre code')).toContainText('pnpm add -D weapp-vite') + await expect(page.getByLabel('安装命令', { exact: true })).toContainText('pnpm add -D weapp-vite') await expect(page.getByRole('link', { name: '查看 npm' })).toHaveAttribute('href', 'https://www.npmjs.com/package/weapp-vite') await expect(page.locator('script[type="application/ld+json"]')).toHaveCount(3) }) @@ -241,13 +245,13 @@ test('publishes indexable SEO resources and keeps 404 out of the index', async ( await expect(page.locator('meta[name="robots"]')).toHaveAttribute('content', 'noindex, follow') }) -test('planned project exposes complete placeholder release data', async ({ page }) => { +test('published Varo project exposes current release data', async ({ page }) => { await page.goto('/projects/varo/') await expect(page.getByRole('heading', { level: 1, name: 'Varo' })).toBeVisible() await expect(page.getByRole('link', { name: '查看源码' })).toHaveAttribute('href', 'https://github.com/daguanren21/Varo') - await expect(page.getByRole('link', { name: '阅读文档' }).first()).toHaveAttribute('href', 'https://github.com/daguanren21/Varo#readme') - await expect(page.getByText('@varo/cli')).toBeVisible() - await expect(page.getByText('v0.0.1')).toBeVisible() + await expect(page.getByRole('link', { name: '阅读文档' }).first()).toHaveAttribute('href', 'https://daguanren21.github.io/Varo/') + await expect(page.getByLabel('安装命令', { exact: true })).toContainText('pnpm dlx @varo-ui/cli add --target weapp button input card') + await expect(page.getByText('v2.1.0')).toBeVisible() await expect(page.getByText('/docs/varo/')).toBeVisible() await expect(page.getByText('GitHub Stars')).toBeVisible() }) diff --git a/apps/web/tests/e2e/sponsors.spec.ts b/apps/web/tests/e2e/sponsors.spec.ts index 507ccb6..05e0c3e 100644 --- a/apps/web/tests/e2e/sponsors.spec.ts +++ b/apps/web/tests/e2e/sponsors.spec.ts @@ -274,15 +274,3 @@ test('keeps filters and canvases when the user switches theme', async ({ page }) await expect(graphs.locator('[data-status]')).toHaveText('1 个节点') await expect(graphs.locator('canvas')).toHaveCount(2) }) - -test('shows a sponsor initial when an external avatar fails', async ({ page }) => { - await page.goto('/pricing/') - const image = page.locator('.pricing-public-sponsor img').first() - if (await image.count() === 0) { - test.skip() - } - const fallback = image.locator('xpath=following-sibling::span[1]') - await image.evaluate(element => element.dispatchEvent(new Event('error'))) - await expect(image).toBeHidden() - await expect(fallback).toBeVisible() -})