@devfellowship/ux-paths-capture

中文文档
0.4.0发布于 2026/10/05MITTypeScriptES Module近 30 天下载 5480

DFL UX Paths 捕捉制取出:一个构建时的数据源印章,一个决定性的浏览器,以及将已渲染的屏幕转换为区域. json, @devfellowship/ux-paths-spec描述.

中文使用文档
文档目录14 节
  1. 为什么这是包裹
  2. 通用屏幕 react-native ——0.4.0 (中文(简体) )
  3. QQ 邮票是建立时间和仅抓取
  4. 三个条目
  5. 盖章一个建筑
  6. 抓取屏幕
  7. 在另一个取景口捕捉—— VIEWPORT_PRESETS (0.3.0) (中文(简体) )
  8. 这两个文件是PAIR
  9. 像素稳定是一站式的承诺
  10. 🕒 new Date() 被冻结. Date.now() 在虚拟时钟上运行
  11. QQ 静态页面不是被画过的页面
  12. 何为不归咎,为何如此
  13. 回读地图
  14. 许可证

@devfellowship/ux-paths-capture (英语)

这个 生产商 半个 UX 地图: 它用源文件标记一个建筑和 线条,该线条将每个元素都写出,并按已提供的页面行走,然后写出 regions.json 那个 @devfellowship/ux-paths-spec 描述.

他们让一个设计师点击一个截图区域 得到准确的 文件——没有模式调用,也没有复制应用程序的寄存器 读者的一面.

npm install --save-dev @devfellowship/ux-paths-capture@^0.4.0

为什么这是包裹

两个应用以这种方式捕捉自己, 他们生活在不同的 GitHub 组织,所以任何一种都无法读取对方的来源。 副本 本来是 第三届 执行一份合同——读者一半 已经将第二个记录为债务.

两个制片人像两个读者一样漂移,漂移是看不见的: 在单击后解析出错误的文件时,两者都保持绿色。 npm 跨越 无法设置的边界.

通用屏幕react-native ——0.4.0 (中文(简体) )

一个屏幕从 View 编号 : Text 编号 : Pressable 联 合 国 react-native由 反应-内生-web,没有小写标记,所以主机-元素规则没有邮票. 从0.4.0起,其标记受从 react-native (或 react-native-web获得 dataSet={{ source: "<file>:<line>" }},哪个 反应-内生-网络制成相同 data-source="<file>:<line>" 属性。 没有 读者变化. ux-paths-assert-no-stamp 探测到 dataSet 表格形式a 捆绑也一样, 因为那里属性名称是在运行时构建的 .

QQ 邮票是建立时间和仅抓取

它永远不能生产。 有两个独立的原因:

  1. 体重. 每个主机元素一个属性,在每个屏幕的每个元素上. 对于最终用户来说,这是致命的有效载荷.
  2. 公开. 印章发布应用程序的内部文件布局 进入DOM,任何打开dev工具的人读取. 用于封闭源代码 应用程序是一个披露控制,而不是大小问题.

大门是 默认缺失的环境变量。这不是 捆绑模式: 抓取构建 实值 一个生产模式的建筑, 因为文物 船上的文物,减去印花 —— 要印章时, 模式是真实的 财务报告和审定财务报表 真实的 释放.

证明对文物的默认,而不是配置,用这个 包装船:

# the release build — expect ZERO
npx ux-paths-assert-no-stamp dist

# the capture build — expect MORE THAN ZERO
npx ux-paths-assert-no-stamp dist --expect-present

运行 两者 在中央情报局。 第二,是什么保持了第一个诚实: 一个grep for a 通常不免费通行证的字符串,如果 探测器坏了 垃圾箱也会在每次运行时自行测试自己的探测器,以及 拒绝空目录或缺少目录.

⚠️ 漏出是文件和线的属性 BOUND,没有字 data-source 出现的地方。 解释自己抓取的应用程序 管道将这个名称放入用户界面副本,副本被捆绑起来—— 此检测器的第一个版本只计算了名称, 并且失败了 干净的建筑。 一个为事情而开枪的警卫是个工程师 学会了推翻, 和过度的披露控制 比没有.

三个条目

导入需求持有
@devfellowship/ux-paths-capture无邮票转换器、组件命名器、区域建设器、文物探测器
…/vitevite (可选对等者,仅类型)作为 Vite 插件的邮票
…/playwright@playwright/test (可选对等者,仅类型)确定性浏览器, DOM 行走, 画布- 链接读取, 双写器

拆分让根可以被没有捆绑器和浏览器的东西导入 ——一个CI后卫,一个MCP工具,一个平庸的节点脚本.

盖章一个建筑

// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import { sourceStamp } from "@devfellowship/ux-paths-capture/vite";

export default defineConfig({
  plugins: [
    react(),
    // Returns `undefined` when the switch is off, and `undefined` is a valid
    // member of `plugins` — so there is one gate, in one place.
    sourceStamp({ root: __dirname }),
  ],
});

默认开关是 UX_PATHS_SOURCE_STAMP。一个已经拥有的应用程序 它自己的拼写保持它:

sourceStamp({ root: __dirname, envVar: "MY_APP_SOURCE_STAMP" });

共有之事是出出门,不是出弦. 重命名一个能起作用的开关 抓取已设定的工作将静默地禁用该工作 .

抓取屏幕

软件包拥有每套应用程序都一样的东西: 定型浏览器,DOM行走和几何. 故意这样做的 没有 自己的导航或结算策略——一个应用程序等待 data-testid, (中文(简体) ), 另一个拍摄,直到连续两个相片相同地散开,第三个相片接一 认证门先。 这些是应用程序的属性,而不是地图的属性.

边界是"应用特定",而不是"与定居有关的一切": readCanvases 财务报告和审定财务报表 settleCanvases 在软件包中是因为空 <canvas> 是一个关于平台的事实, 各地读取相同。 他们 他们不拒绝。 见下文.

import { chromium } from "@playwright/test";
import {
  CAPTURE_CONTEXT_OPTIONS,
  CAPTURE_LAUNCH_ARGS,
  applyFreezeStylesheet,
  installDeterminism,
  writeCapturePair,
} from "@devfellowship/ux-paths-capture/playwright";

const browser = await chromium.launch({ args: [...CAPTURE_LAUNCH_ARGS] });
const context = await browser.newContext(CAPTURE_CONTEXT_OPTIONS);
const page = await context.newPage();

await installDeterminism(page); // BEFORE the first navigation
await page.goto("/login");
await applyFreezeStylesheet(page); // AFTER every navigation
// …your own settle policy here…
const canvas = await settleCanvases(page); // null when the screen has no canvas

const png = await page.screenshot({
  fullPage: false,
  animations: "disabled",
  caret: "hide",
  scale: "css",
});

await writeCapturePair(page, {
  outDir: "capture/login",
  screen: "login",
  root: process.cwd(), // where a stamped path is resolved from
  png,
});

写着 screenshot.png 财务报告和审定财务报表 regions.json 并肩而来.

在另一个取景口捕捉—— VIEWPORT_PRESETS (0.3.0) (中文(简体) )

捕捉是屏幕的照片 在一个视图端口,直到0.3.0为止 视点是一个常数。 它现在是一个参数.

import {
  VIEWPORT_PRESETS,
  captureContextOptions,
  captureDirName,
  resolveViewportSpec,
  screenshotMetaFor,
} from "@devfellowship/ux-paths-capture/playwright";

const { name, preset, custom } = resolveViewportSpec(process.env.VIEWPORT ?? "desktop");
const context = await browser.newContext(captureContextOptions(preset));
// …capture as above…
await writeCapturePair(page, { outDir: captureDirName("login", preset), /* … */ });
预设大小旗帜
desktop (默认)1280x800 (英语)—— 说
mobile390x844 (英语)isMobile, (中文(简体) ), hasTouch

两者都是 deviceScaleFactor: 1。 。 。 .

captureContextOptions("desktop") 与 CAPTURE_CONTEXT_OPTIONS, (中文(简体) ), 和单位测试 声称它. CAPTURE_VIEWPORT 财务报告和审定财务报表 CAPTURE_CONTEXT_OPTIONS 停止出口并停止1280x800——任何消费者已经进口的东西都没有移动.

🚨 isMobile 这是重要的领域, 它在图像中是看不见的. A 类 390x844 语境 无 它是一个狭窄的桌面,而不是一个电话: @media (hover: hover) 财务报告和审定财务报表 pointer: fine 分支仍然采用桌面路径, 因此,捕捉照片的布局 从来没有显示任何电话用户 - 它这样做 从决定性的角度来说,这是造成错误持久的原因。 这就是为什么 resolveViewportSpec("390x844") 返回时 移动预设包括旗帜, 而不是光着身子 A 类 WxH 匹配没有预设返回 custom: true 所以打电话的人可以大声说出来.

🚨 deviceScaleFactor 保留1,而不是3个. 剧作家自己的 iPhone 13 预设为 减贫战略 3. 采用这一标准将是一项新的确定性主张(此处没有衡量标准为: 3) 和一项新的区域预测索赔(scale: 'css' 共享一个坐标空间 与 getBoundingClientRect() 仅限DPR 1。 价格是移动图像 为 390x844 CSS 像素而不是 1170x2532 设备像素: 真正的移动 版式 在 1x 时, 区域地图仍然正确 .

相对所起之处. captureDirName 将默认视图端口写入 <screen_id>/ 和以前一样, 和所有其他的景点 到平地 <screen_id>@<WxH>/。内部的文件名称不变,而且 regions.json 记录真实的取景口, 所以一对是自我描述, 即使从它的 目录。 嵌入 <screen_id>/<WxH>/ 被否决了,它打破了每一个读者 将目录名称作为屏幕 id .

screenshotMetaFor(preset) 返回时 { platform, orientation, viewport } 3个换1个 screens[].screenshots[] 输入,所以一个被观测到的流的生产者 文档不硬性类型 web编号 :landscape 再来一次.

这两个文件是PAIR

regions.json 描述一个图像的几何形状, 在图像本身 像素空间 — CSS 像素, deviceScaleFactor: 1风景点 直肠 放置在不同的图像旁边比完全没有直角更糟糕.

查看端口不剪接 fullPage 具体原因: getBoundingClientRect() 说取景口坐标和铬 调整大小 视图端口 拍出一整页的镜头 fixed编号 :sticky 要素 并可以挂载读取矩形时未挂载的内容.

像素稳定是一站式的承诺

下游所有东西都比较两个截图 问diff是否到达 零,所以冻结是合同的一部分。 不过 格莱弗光栅化属于 给机器: 不同的 FreeType 或字体配置使文本与 不同的反变相。 一个主机上的两个捕捉器是同字节;两个 不同主机上的捕获不承诺。 不同东道类的比较 必须在一个容器里运行 任何意义.

performance.now() - 故意地留下真实的- 冻结它拖住反应的 调度器和每个 requestAnimationFrame 循环,交易化妆品摇摆 一个绞刑.

🕒 new Date() 被冻结. Date.now() 在虚拟时钟上运行

已更改 0.2.0 (中文(简体) ),它改变每个消费者的行为.

在0.2.0之前,两者都被冻结。 这让每一次的测量回报 0, 静态禁用 lodash.debounce, (中文(简体) ), lodash.throttle 和任何东西 以减掉两个时钟读数来决定 Date.now() - last >= wait 实值 0 >= 1虚假的,永远的. kapsule (单位:千美元) react-force-graph-2d) 附表 它的文摘是这样的, 所以一个力图从来没有列出 一个空白的画布是 作为屏幕发布,有稳定的文摘和0退出代码.

现在:

时钟行为
new Date()冰冻在时代,这就是DOM
Date.now()epoch + virtual elapsed,而虚拟过期的垫款只有在 setTimeout 编号 : setInterval 回叫起火,到计时器的时间

装有 setTimeout(fn, 300) 因此,当 它运行,在一个闲散的宿主上,一个满载的宿主上, 交易内容是:

  • Date.now() 财务报告和审定财务报表 new Date().getTime() 不再认同,通过虚拟 时间已过.
  • 决定主义变成有条件的. 冰冻常数是相同的 运行,无论页面如何操作;虚拟时钟仅在同时运行 中,页面以相同的顺序排列相同的计时器。 字节稳定现在是 测量,不是这个文件的属性——用你自己的抓取.
  • 一个生的 Date.now() 屏幕上打印的值可以移动. 格式化日期 无法:来自 new Date()。 。 。 .

installDeterminism(page, { clock: "frozen" }) 恢复旧行为 确切地说,对于一个需要两个钟表同意的捕捉, 并且没有它的任何东西 使措施过时.

QQ 静态页面不是被画过的页面

settleCanvases(page) 等待到每个 <canvas> 携带的InK——不止一个 在它自己的后缓冲器中具有明显的像素值——直到这道墨水停止了变化. 两个事实都从布告中读出 getImageData,不等待出来.

它之所以存在,是因为两个相同的 BLANK 框架的散去相同,所以是一个空的图案 在第一次尝试中通过射击到稳定检查 它回来了 null 编号 没有画布的屏幕,以及 { painted: false, reason } 当预算用完时.

它报告;它不拒绝. writeCapturePair 从不咨询它。 一个 空画布是一个应用程序的缺陷和一个空白的正确第一帧 画出另一块地表,这个包不能将它们分开——所以 决定不留图像是消费者的,它应该让它:一个洞 在映射图中,一个自信的空白图片是不可见的.

何为不归咎,为何如此

  • 第三方组成部分 从自己汇编的联署材料中释放自己的DOM。 这个 邦德从未见过他们的JSX.
  • 预编译的工作空间包 已经把他们的JSX变成了 jsx() 在捆绑者逃跑前打电话 首方代码,仍未分出.
  • React.createElement 财务报告和审定财务报表 dangerouslySetInnerHTML - 没有JSX标签,没有 邮票.

在未分配DOM上着陆的区域通过最近的 已盖章 祖先,这是挂载第三方组件的文件。 这是 诚实的答案, 而这是一个设计师可以采取行动.

回读地图

resolveRegionAt 是再出口到这里,但它是 定义 内 @devfellowship/ux-paths-spec。一个查看器应该从那里导入 全部跳过此软件包 用于浏览器.

许可证

麻省理工学院

版本与发布记录

@devfellowship/ux-paths-capture 共发布 4 个版本,首次发布于 2026/08/14;过去 12 个月发布了 4 个版本。

版本发布日期距今
0.4.0latest2026/10/051 个月前
0.3.02026/09/022 个月前
0.1.12026/08/142 个月前
0.1.02026/08/142 个月前

关于 @devfellowship/ux-paths-capture 的常见问题

@devfellowship/ux-paths-capture 是什么?

DFL UX Paths 捕捉制取出:一个构建时的数据源印章,一个决定性的浏览器,以及将已渲染的屏幕转换为区域. json, @devfellowship/ux-paths-spec描述.

如何安装 @devfellowship/ux-paths-capture?

在项目目录运行 npm install @devfellowship/ux-paths-capture,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 ux-paths-assert-no-stamp,可以用 npx ux-paths-assert-no-stamp 直接运行。

@devfellowship/ux-paths-capture 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@devfellowship/ux-paths-capture 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@devfellowship/ux-paths-capture 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@devfellowship/ux-paths-capture 可以商用吗?

@devfellowship/ux-paths-capture 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@devfellowship/ux-paths-capture 的下载量有多少?

根据 npm 官方下载统计,@devfellowship/ux-paths-capture 在 2026/10/12 – 2026/11/10 这 30 天内被下载 5,480 次,日均约 183 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@devfellowship/ux-paths-capture 还在维护吗?

最新版本 0.4.0 发布于 2026/10/05(1 个月前);至今共发布 4 个版本,其中过去 12 个月发布了 4 个;首次发布于 2026/08/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。