PastePreset
PastePreset 是一个 privacy-first、纯浏览器端的图片处理 Web app。package.json、README.md、docs/pwa-offline-support.md 和 public/manifest.
- TypeScript web
- React app
- Progressive web app
- Playwright e2e
- Storybook accessibility
- Storybook component QA
目录
技术栈
运行与交付
- CI 工作流
- ci.yml
- deploy.yml
- 能力标记
- github_actions
- package_json
依赖与工具
- package.json
- 开发依赖
- @biomejs/biome
- @playwright/test
- @storybook/addon-a11y
- @storybook/addon-docs
- 生产依赖
- @iconify/icons-circle-flags
- @iconify/icons-mdi
- @iconify/react
- exifr
- 项目脚本
- build
- build-storybook
- check
- dev
配置与质量
- 配置文件
- .gitignore
- biome.json
- lefthook.yml
- package.json
- tsconfig.app.json
- tsconfig.json
- tsconfig.node.json
{
"ci_workflows": [
"ci.yml",
"deploy.yml"
],
"configs_root": [
".gitignore",
"biome.json",
"lefthook.yml",
"package.json",
"tsconfig.app.json",
"tsconfig.json",
"tsconfig.node.json"
],
"markers_present": [
"github_actions",
"package_json"
],
"package_json": {
"deps_dev": [
"@biomejs/biome",
"@playwright/test",
"@storybook/addon-a11y",
"@storybook/addon-docs",
"@storybook/addon-links",
"@storybook/jest",
"@storybook/react-vite",
"@storybook/test",
"@storybook/test-runner",
"@storybook/testing-library",
"@tailwindcss/vite",
"@types/bun",
"@types/node",
"@types/react",
"@types/react-dom",
"@vitejs/plugin-react",
"@vitest/coverage-v8",
"@vitest/ui",
"autoprefixer",
"daisyui"
],
"deps_prod": [
"@iconify/icons-circle-flags",
"@iconify/icons-mdi",
"@iconify/react",
"exifr",
"heic2any",
"jszip",
"piexifjs",
"react",
"react-dom"
],
"scripts": [
"build",
"build-storybook",
"check",
"dev",
"format",
"lint",
"preview",
"storybook",
"storybook:ci",
"test",
"test-storybook",
"test-storybook:runner",
"test:e2e",
"test:e2e:pwa",
"test:e2e:ui"
]
}
}Purpose
PastePreset 是一个 privacy-first、纯浏览器端的图片处理 Web app。package.json、README.md、docs/pwa-offline-support.md 和 public/manifest.webmanifest 共同表明,这个项目不只是普通 React/Vite SPA,而是明确把“可安装、可离线启动、图片处理全在本地完成”的 owner-facing 产品面当成长期 contract 维护。
Taxonomy
- Tags: TypeScript web, React app, Progressive web app, Playwright e2e, Storybook accessibility, Storybook component QA
- Why / evidence: 这些 tags 来自 checked-out repo 和 catalog record。主要证据包括
package.json、index.html、public/manifest.webmanifest、public/pwa/、src/pwa/registerServiceWorker.ts、scripts/build-sw.mjs、playwright.config.ts、playwright.pwa.config.ts、tests/e2e-pwa/pwa-offline.spec.ts、.storybook/main.ts、.storybook/preview.tsx、docs/pwa-offline-support.md。Topic token 的大小写以对应技术/工作流的官方写法为准;slug 只作为稳定 ID,不直接充当项目标题。
Repository map
src/是 React 应用本体;src/lib/、src/hooks/和src/components/围绕图片输入、处理、输出与设置构成完整前端 runtime。public/manifest.webmanifest与public/pwa/保存 install-facing metadata、icons、maskable icons 和 screenshots。src/pwa/registerServiceWorker.ts、scripts/build-sw.mjs、scripts/sw-template.js负责 service worker 注册与构建时 precache 注入。tests/e2e-pwa/、playwright.pwa.config.ts和docs/pwa-offline-support.md说明这个 repo 把 PWA 行为单独当作验证面,而不是塞进普通 smoke test。.storybook/与public/storybook/保持组件级 QA 和 a11y surface,但它们不是 PWA 交付面的替身。
Runtime and delivery
package.json 的 build 会先写入版本信息,再执行 vite build,最后运行 node scripts/build-sw.mjs,说明离线 app shell 与 version.json 一样属于正式产物,而不是部署后的临时拼装。index.html 和 public/manifest.webmanifest 把 start_url、scope、display: standalone、maskable icons 和 apple-touch-icon 写成稳定 install metadata;test:e2e:pwa 则通过 playwright.pwa.config.ts 走独立浏览器路径,验证 service worker 就绪、离线启动和核心流程。
Architecture notes
这个项目的关键架构边界是“处理逻辑完全本地执行,但 app shell 仍然需要正式的 PWA 运行时 contract”。docs/pwa-offline-support.md 明确要求:先在线访问并安装,之后离线启动时仍要完整渲染 UI;更新采用 next-launch 语义,不允许 skipWaiting() 或 mid-session 强刷。scripts/build-sw.mjs 用 Workbox injectManifest 维护 precache,src/pwa/registerServiceWorker.ts 负责等待/接管逻辑,说明这里的 PWA 不是营销标签,而是真正影响版本切换、资源缓存和 owner handoff 的 runtime 设计。
Workflow and quality gates
前端质量门禁分三层:vitest 负责单元测试,playwright test 负责常规 e2e,playwright test -c playwright.pwa.config.ts 负责 PWA/offline 专项路径。Storybook 安装了 @storybook/addon-a11y,并通过 test-storybook 保持组件 QA;CI 与 deploy workflow 则让 build + PWA asset + 测试链路一起进入交付面。对于这个仓库,单纯 vite build 通过并不能证明交付完成,PWA 专项验证是必需门禁。
Reusable decisions
- 把 PWA 设计文档单独写进
docs/pwa-offline-support.md,比在 README 里顺带提一句“支持离线”更可靠。 - 为 PWA 保留独立的
playwright.pwa.config.ts和tests/e2e-pwa/,能避免 service worker / offline 逻辑被普通 e2e 稀释掉。 - 让
build显式串联版本写入、静态构建和 service worker 注入,可以防止version.json或其它 UI-critical 资产漏进 precache。 - 对 update lifecycle 采取 next-launch 策略,并在设计文档里明确禁止
skipWaiting()自动接管,是很值得复用的默认习惯。
Risks and open questions
- iOS Safari 的离线缓存与剪贴板能力仍有平台限制,PWA contract 需要把“best effort”边界说清楚。
- HEIC 转换相关动态产物若没有被 precache 完整覆盖,离线成功率会看起来随机。
- 这个仓库是纯前端产品面,后续若引入云同步或外部 API,就必须重新审查当前“离线即完整功能”的假设。
Evidence index
README.mdpackage.jsonindex.htmlpublic/manifest.webmanifestpublic/pwa/scripts/build-sw.mjsscripts/sw-template.jssrc/pwa/registerServiceWorker.tsplaywright.config.tsplaywright.pwa.config.tstests/e2e-pwa/pwa-offline.spec.ts.storybook/main.ts.storybook/preview.tsxdocs/pwa-offline-support.md
相关内容
Playwright e2e
主题Playwright e2e 指仓库把真实浏览器里的关键用户流程当成正式质量门禁,而不是“顺手写了几条页面脚本”。它强调的是产品行为验证:路由、认证、交互链路、浏览器 API、嵌入式控制台或多 runtime 页面组合,必须在接近真实使用路径的浏览器环境里被证明可用(projects/blog-26.md、projects/proxy-broker.md、projects/octo-rill.
Progressive web app
主题Progressive web app 在这套 playbook 里不是“网页顺手带个 manifest”的统称,而是“把一个 Web surface 当成可安装应用去维护”的工程模式。
React app
主题React app 标记 React 是主要用户界面、管理台、控制台或嵌入式操作面 runtime。这里关心的是 route、component tree、client state、表单流、dashboard 交互和前端构建后的真实运行边界,而不是“项目依赖里有 React”。 这个 Topic 用来回答“用户实际操作的是不是一个 React runtime,以及它在系统里承担什么职责”。
Storybook accessibility
主题Storybook accessibility 表示 Storybook 不只是组件展示,还明确引入 a11y audit 能力,通常是 @storybook/addon-a11y 或等价的 browser-backed Axe sweep。它关注 story-level 可访问性信号,例如对比度、ARIA 基础错误、表单语义和交互状态,而不是泛化的 Storybook 文档能力。
Storybook component QA
主题Storybook component QA 表示仓库把 Storybook 当作组件级文档、状态枚举、视觉检查或 interaction smoke 的稳定入口。它不等同于 Storybook accessibility:只有项目明确引入 a11y addon 或等价 Axe sweep 时,才同时打 accessibility Topic。这个拆分用于避免“只要有 Storybook 就叫 a11y”的误判。
TypeScript web
主题TypeScript web 表示项目把 TypeScript 作为一个或多个 Web surface 的主语言,并围绕它建立 workspace scripts、typecheck、bundler、lint/format、env contract 和前端构建门禁。这里的主语不是“仓库里出现了 .ts 文件”,而是 TypeScript 已经决定了维护者怎样启动、构建、校验和交付实际 Web surface。