mcpField
P
playwright-release-notes

playwright-release-notes

github.com/microsoft开发98.8k14 次安装今天更新
代码仓库

关于 playwright-release-notes

playwright-release-notes 是帮助贡献者编写 Playwright 发布文档的技能。它指导编写 Node.js 发布说明及 Python、Java 和 .NET 译文,并将各语言章节转换为对应的 GitHub 发布说明 Markdown。

主要功能

  1. 01编写 Node.js 发布说明
  2. 02翻译为 Python、Java 和 .NET 版本
  3. 03适配各语言的 API 名称和示例
  4. 04转换为 GitHub 发布说明 Markdown
  5. 05检查文档链接

适用场景

  1. 01准备四种语言的发布文档
  2. 02调整各语言的 API 示例
  3. 03生成并验证发布公告 Markdown

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/microsoft/playwright --skill playwright-release-notes

安装后在 Claude Code 中输入/playwright-release-notes确认已加载。

详细介绍

发布说明

在此技能中,1.xx 表示发布版本(例如 1.64)。

docs/src/ 中的四个文件均包含一个 ## Version 1.xx 章节:

语言说明文档基础 URLGitHub 发布所在仓库
Node.jsrelease-notes-js.mdhttps://playwright.dev/docs/microsoft/playwright
Pythonrelease-notes-python.mdhttps://playwright.dev/python/docs/microsoft/playwright-python
Javarelease-notes-java.mdhttps://playwright.dev/java/docs/microsoft/playwright-java
.NETrelease-notes-csharp.mdhttps://playwright.dev/dotnet/docs/microsoft/playwright-dotnet

在同一个 PR 中编写 Node.js 说明和另外三种语言的译文,确保每种语言在开始发布时都有对应的说明。之后,各语言仓库只需添加各自的重要变更,并根据对应章节编写 GitHub 发布说明(第 3 步)。

1. Node.js 说明

在 docs/src/release-notes-js.md 中,在上一版本之前添加 ## Version 1.xx 章节,并参考之前的版本:

  • 首先列出亮点,每项使用带有 emoji 的标题和简短示例。请队友协助撰写。
  • 接着添加 ### New APIs,并使用 #### 分组,然后添加 ### Breaking Changes ⚠️、### Announcements 和 ### Browser Versions。使用 node utils/print_versions.js 输出浏览器版本。
  • 使用文档链接宏引用 API:[`method: Page.frameLocator`]、[`property: Page.webmcp`]、[`event: Page.dialogClosed`]、[`option: Tracing.start.ariaSnapshots`]、[Locator]。各语言的文档会使用对应语言的名称显示这些内容。
  • 使用相对路径链接其他文档页面:[test locks](./test-parallel.md#test-locks)。

2. Python、Java 和 .NET 翻译

在 release-notes-python.md、release-notes-java.md 和 release-notes-csharp.md 中,分别在上一版本之前添加一个 ## Version 1.xx 部分。将其从 Node.js 部分翻译而来。对比这些文件的 Version 1.63 部分,查看过去的翻译遗漏或改动了哪些内容。

对于每种语言:

  • 保留以下结构:带表情符号标题的亮点、带 #### 分组的 ### New APIs、### Breaking Changes ⚠️、### Announcements 和 ### Browser Versions。
  • 删除该语言不支持的内容:
    • 测试运行程序:@playwright/test、test.*、配置、fixture、项目、报告器和 npx playwright test 选项
    • UI 模式、HTML 报告、组件测试和 VS Code 扩展
    • 仅限 TypeScript 的功能(泛型、JSX、tsconfig)和 devices 描述符
    • 所有 langs 不包含该语言(python、java、csharp)的 API。请检查 docs/src/api/ 中的 langs;多个方法共用的选项定义在 docs/src/api/params.md 中。
  • 使用与 Node.js 不同的语言 API:
    • 特定语言的选项有自己的 langs。例如,recordVideoFps 的 langs 为 csharp, java, python,而 Node.js 使用 recordVideo.fps。
    • alias-<lang> 用于重命名成员,例如 LocatorAssertions.toBeVisible 的 alias-java: isVisible。
    • 同级仓库中的生成 API 可用于确认名称:../playwright-python/playwright/sync_api/_generated.py、../playwright-java/playwright/src/main/java/com/microsoft/playwright/ 和 ../playwright-dotnet/src/Playwright/API/Generated/。
  • 如果 Node.js 示例通过 playwright.config.ts 展示库功能,则改为展示 API 调用。例如,1.64 的视频配置改成了调用 Screencast.start 和 Screencast.showActions。
  • 将 API 链接保留为文档链接宏;选项不同的语言应链接到该语言自己的选项([`option: Browser.newContext.recordVideoFps`])。纯文本中使用该语言的名称。
  • 相对链接必须指向该语言中存在的页面:*-js.md 页面仅适用于 Node.js。npm run doc 会报告各语言的失效链接。
  • 不要添加仅由某种语言的移植版本引入的改动。语言仓库会将这些内容添加到各自的发布说明中。

按照各语言的风格改写代码示例。infra 工作流会检查 python、java 和 csharp 代码片段的语法。

Python
  • 使用同步 API:page.get_by_role("button").click()。使用蛇形命名法和 Python 值(True、False、None)。
  • 选项改为关键字参数:page.get_by_role("button", name="Save")。对象和数组改为字典和列表:size={"width": 1920, "height": 1080}。
  • Aria 角色和其他字符串值保留为字符串:"button"、"ai"。
  • 事件:page.on("dialogclosed", handler)。断言:expect(locator).to_have_text([...])。使用 print(...) 输出。
  • 使用 alias-python 名称:route.continue_()、locator.or_()、page.expect_request()。
  • 命令:写 playwright install,不要写 npx playwright install。
Java
Node.jsJava
await page.goto('...')page.navigate("...");:无需 await,使用双引号、分号和类型化局部变量(Locator dialog = ...)
page.getByRole('button', { name: 'Save' })page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Save"))
选项对象 { path: 'video.webm', fps: 60 }选项构建器 new Screencast.StartOptions().setPath(Paths.get("video.webm")).setFps(60)
对象字面量 { name: 'session-id', value: '42', url }值类 new Cookie("session-id", "42").setUrl(url)
['a', 'b']、{ a: 2 }Arrays.asList("a", "b")、Map.of("a", 2);断言参数使用 new String[] {"a", "b"}
属性 page.webmcp、context.tracingGetter page.webmcp()、context.tracing()
事件 page.on('dialogclosed', handler)page.onDialogClosed(handler)
expect(locator).toHaveText(...)assertThat(locator).hasText(...)。同理,toBeX → isX、toHaveX → hasX、toContainX → containsX、toMatchX → matchesX
route.continue() 及其他带有 alias-java 的成员别名,例如 route.resume()
npx playwright install --no-removemvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --no-remove"
在正文中使用 "array"、undefined、'ai'"list"、null、"ai"
.NET
Node.js.NET
await page.goto('...')await page.GotoAsync("...");:成员使用 PascalCase,异步方法带 Async 后缀,局部变量使用 var,使用双引号和分号
page.getByRole('button', { name: 'Save' })page.GetByRole(AriaRole.Button, new() { Name = "Save" })
选项对象 { path: 'video.webm', fps: 60 }选项初始化器 new() { Path = "video.webm", Fps = 60 }
嵌套对象 size: { width: 1920, height: 1080 }Size = new() { Width = 1920, Height = 1080 }
对象字面量 { name: 'session-id', value: '42', url }new Cookie { Name = "session-id", Value = "42", Url = url }
['a', 'b']、自由格式对象 { a: 2 }new[] { "a", "b" }、匿名对象 new { a = 2 }
字符串字面量联合值 'ai'、'button'枚举成员 AriaSnapshotMode.Ai、AriaRole.Button
属性 page.webmcp、context.tracing属性 page.Webmcp、context.Tracing
事件 page.on('dialogclosed', handler)page.DialogClosed += (_, dialog) => { ... };
expect(locator).toHaveText(...)await Expect(locator).ToHaveTextAsync(...);
console.log(x)Console.WriteLine(x);
带有 alias-csharp 的成员别名,例如 page.request → page.APIRequest
联合类型选项,例如作为列表的 httpCredentials每种类型对应一个属性,例如 HttpCredentialsList
npx playwright install --no-removepwsh bin/Debug/netX/playwright.ps1 install --no-remove
正文中的选项名称(fontSize)、undefinedFontSize、null

为全部四个文件提交一个 PR,标题为 docs: release notes for v1.xx。合并后,使用 playwright-cherry-pick skill 将其 cherry-pick 到 release-1.xx。

3. GitHub 发布说明 Markdown

每个仓库都会发布对应语言的 GitHub 发布说明,内容由 release-1.xx 上的 ## Version 1.xx 章节转换为 Markdown。请自行转换说明:

  • 删除 ## Version 1.xx 标题。将其他所有标题提升一级(### 变为 ##,#### 变为 ###)。

  • 将每个链接宏替换为完整链接:使用顶部表格中的该语言文档基础 URL,加上下面的路径。链接文本使用该语言的名称:

    宏文档基础 URL 之后的路径Node.jsPythonJava.NET
    [Locator]api/class-locatorLocatorLocatorLocatorLocator
    [`method: Page.frameLocator`]api/class-page#page-frame-locatorpage.frameLocator()page.frame_locator()page.frameLocator()Page.FrameLocator()
    [`method: Page.ariaSnapshot`]api/class-page#page-aria-snapshotpage.ariaSnapshot()page.aria_snapshot()page.ariaSnapshot()Page.AriaSnapshotAsync()
    [`method: Locator.first`]api/class-locator#locator-firstlocator.first()locator.firstlocator.first()Locator.First
    [`property: Page.webmcp`]api/class-page#page-webmcppage.webmcppage.webmcppage.webmcp()Page.Webmcp
    [`event: BrowserContext.dialogClosed`]api/class-browsercontext#browser-context-event-dialog-closedbrowserContext.on('dialogclosed')browser_context.on("dialogclosed")browserContext.onDialogClosed()BrowserContext.DialogClosed
    [`method: LocatorAssertions.toBeVisible`]api/class-locatorassertions#locator-assertions-to-be-visibleexpect(locator).toBeVisible()expect(locator).to_be_visible()assertThat(locator).isVisible()Expect(Locator).ToBeVisibleAsync()
    [`option: Page.content.includeShadow`]api/class-page#page-content-option-include-shadow`includeShadow``include_shadow``includeShadow``IncludeShadow`
    [Playwright MCP](./getting-started-mcp.md)getting-started-mcpPlaywright MCPPlaywright MCPPlaywright MCPPlaywright MCP
  • 图片 ![alt](./images/foo.png) 在每种语言中都会变为 ![alt](https://github.com/microsoft/playwright/blob/main/docs/src/images/foo.png?raw=true)。

页面名称为 class- 加上小写类名。锚点由 kebab-case 格式的类名和成员名组成,因此 APIRequestContext.addCookies 会变为 api-request-context-add-cookies。选项会添加 -option-<name>,事件会添加 -event-<name>。锚点使用 docs/src/api/ 中的名称,即使某种语言重命名了成员也是如此,因此 Java 的 isVisible() 链接到 #locator-assertions-to-be-visible。

链接文本因语言而异:

  • Node.js: 类名使用小驼峰格式(page、apiRequestContext、testConfig)。方法带 (),属性不带,事件变为 on('<event in lower case>'),断言以 expect(locator).、expect(page). 或 expect(response). 开头。
  • Python: 类名和成员名使用 snake_case(browser_context、api_request_context)。方法带 ()。如果 _generated.py 使用 @property 声明成员,则该成员是属性,不带 ()。事件变为 on("<event in lower case>"),断言以 expect(locator). 开头。
  • Java: 类名使用小驼峰格式,成员名使用 alias-java 中的名称。方法和属性带 (),事件变为 on<Event>(),断言以 assertThat(locator). 开头。
  • .NET: 类名不带接口前缀 I(Page、APIRequestContext),成员名与生成的 I<Class>.cs 中的声明完全一致。异步方法带 Async 后缀和 (),同步方法带 (),属性和事件不带括号。断言以 Expect(Locator). 开头。

检查每个链接是否都能正常跳转。Node.js 文档滚动更新完成后,playwright.dev 就会记录该版本。它提供的是经过压缩的 HTML,因此锚点可能不带引号(id=page-webmcp>):

grep -oE 'https://playwright\.dev/[^) ]+' <notes-file> | sort -u | while read -r url; do
  page=${url%%#*}
  html=$(curl -sfL "$page") || { echo "MISSING PAGE   $url"; continue; }
  if [[ "$url" == *"#"* ]]; then
    anchor=${url#*#}
    grep -qE "id=\"?${anchor}[\" >]" <<<"$html" || echo "MISSING ANCHOR $url"
  fi
done

然后扫描是否有未转换的内容,以及链接文本中是否有多余空格([Page. DialogClosed]、[`HttpCredentialsList `])。第一条命令适用于所有语言;然后运行对应语言的命令。它们不应输出任何内容:

# every language
grep -nE '\[`(method|property|event|option|param): |\]\(\./|\[[A-Z][A-Za-z]*\]([^(]|$)|\[[A-Za-z_]+\. |\[`[^`]+ `\]' <notes-file>
# Python: camelCase names in link text
grep -nE '\[[a-z_]+\.[a-z_]*[A-Z]|\[`[a-z]+[A-Z]' <notes-file>
# Java: JS-style events, assertions and properties
grep -nE "\.on\('|\b(toBe|toHave|toContain|toMatch)[A-Z]|\bawait\b|\barray\b|\bundefined\b|\[[a-z][A-Za-z]*\.[a-z][A-Za-z]*\]\(" <notes-file>
# .NET: lower-case classes or members, JS-style events
grep -nE "\.on\('|\bundefined\b|\[[a-z][A-Za-z]*\.|\[[A-Z][A-Za-z]*\.[a-z]|\[Expect\([a-z]" <notes-file>

如果转换结果表明问题出在注释本身,例如使用了该语言不支持的 API,或示例风格不正确,也请一并修正注释(第 2 步)。否则,问题仍会留在 playwright.dev 上。

评论

支持 Markdown