Skip to main content

API 历史记录介绍 (GSoC 2024)

· 16 min read

Electron API 的历史变更现在将在文档中详细说明。

¥Historical changes to Electron APIs will now be detailed in the docs.


大家好👋,我是 Peter,2024 年 Electron Google Summer of Code (GSoC) 贡献者。

¥Hi 👋, I'm Peter, the 2024 Google Summer of Code (GSoC) contributor to Electron.

在 GSoC 项目期间,我为 Electron 文档及其函数、类等实现了 API 历史记录功能,其方式与 Node.js 文档 类似:允许在 API 文档 Markdown 文件中使用简单但功能强大的 YAML 模式,并在 Electron 文档网站上清晰地显示。

¥Over the course of the GSoC program, I implemented an API history feature for the Electron documentation and its functions, classes, etc. in a similar fashion to the Node.js documentation: by allowing the use of a simple but powerful YAML schema in the API documentation Markdown files and displaying it nicely on the Electron documentation website.

细节

¥Details

API 历史文档系统 / YAML 模式

¥API history documentation system / YAML schema

在 Markdown API 文档中,函数/类/等的历史记录现在以 YAML 代码块的形式直接放置在该项目的标题之后,并用 HTML 注释封装。

¥In the Markdown API documentation, the history for a function/class/etc. is now placed directly after the header for that item in the form of a YAML code block encapsulated by an HTML comment.

#### `win.setTrafficLightPosition(position)` _macOS_

<!--
```

已添加 YAML 历史记录:

¥YAML history
added:

* pr-url:[https://github.com/electron/electron/pull/22533](https://github.com/electron/electron/pull/22533) 变更:

¥pr-url: [https://github.com/electron/electron/pull/22533](https://github.com/electron/electron/pull/22533)
changes:

* pr-url:[https://github.com/electron/electron/pull/26789](https://github.com/electron/electron/pull/26789) description:“让 `trafficLightPosition` 选项在 `customButtonOnHover` 窗口上正常工作。”已弃用:

¥pr-url: [https://github.com/electron/electron/pull/26789](https://github.com/electron/electron/pull/26789)
description: "Made `trafficLightPosition` option work for `customButtonOnHover` window."
deprecated:

* pr-url:[https://github.com/electron/electron/pull/37094](https://github.com/electron/electron/pull/37094) breaking-changes-header:deprecated-browserwindowsettrafficlightpositionposition

```
-->

* `position` [Point](structures/point.md)

Set a custom position for the traffic light buttons. Can only be used with `titleBarStyle` set to `hidden`.
```

`

我认为像 Node.js 文档那样使用 YAML 是最好的方法,因为它易于阅读。API 的历史并不复杂,理想情况下应该尽可能易于编写和阅读。

¥I believe using YAML like the Node.js docs do was the best approach because it
is easy to read. The API history isn't extremely complicated and should ideally
be as easy to write and read as possible.

上面显示的最终设计实际上与我提出的方案有很大不同:

¥The final design shown above is actually significantly different to the one I proposed:

````yaml
<!--
```

已添加 YAML 历史记录:v10.0.0 已弃用:v25.0.0 已移除:v28.0.0 变更:

¥YAML history
added: v10.0.0
deprecated: v25.0.0
removed: v28.0.0
changes:

* 版本:v13.0.0 pr-url:[https://github.com/electron/electron/pull/26789](https://github.com/electron/electron/pull/26789) description:使 `trafficLightPosition` 选项适用于 `customButtonOnHover` 窗口。

¥version: v13.0.0
pr-url: [https://github.com/electron/electron/pull/26789](https://github.com/electron/electron/pull/26789)
description: Made `trafficLightPosition` option work for `customButtonOnHover` window.

```
-->
```

`

一个重大变化是删除了版本号:

¥One large change is the removal of version numbers:

>[...] 关于该提案,我们想指出一个比较重要的变更,该变更在我们审核提案的讨论中提出。[...]
>
> ¥"[...] There’s one somewhat significant change we’d like to call out about
> the proposal, which came up during discussion when we were reviewing proposals.
> [...]
>
> [我们] 决定,缺陷最少的方法是仅使用 PR URL(指向主代码的根 PR),而不是像提案中那样使用硬编码的版本字符串。
>
> ¥[we] decided that the approach with the [fewest] drawbacks would be to only
> use PR URLs (the root PRs to main) instead of hardcoded version strings as in
> the proposal.
>
> 这可以作为单一事实来源,之后可用于获取准确的版本号,并且如果将更改反向移植到其他分支,则无需对主分支进行进一步的文档更改。
>
> ¥This can serve as a single source of truth which can then be used
> to derive exact version numbers, and no further documentation changes on main
> are necessary if the change is backported to other branches."
>
> — David Sanders [(@dsanders11)][dsanders11] 通过 Slack
>
> ¥— David Sanders [(@dsanders11)][dsanders11] via Slack

我们也没有在 API 历史记录中包含移除记录,因为当某个 API 从 Electron 中移除时,它也会从文档中移除。

¥We also didn't include removals in the API History, since when an API is removed
from Electron, it is also removed from the documentation.

### JavaScript 实现 \{#javascript-implementation}

¥JavaScript implementation

我最初计划创建一个新的 `@electron/docs-api-history-tools` npm 包,其中包含用于提取、验证/linting 和转换文档文件中 API 历史记录的脚本。

¥I originally planned to create a new `@electron/docs-api-history-tools`
npm package that would contain scripts for extracting, validating/linting and converting
the API history in the documentation files.

在编码阶段开始前大约一周,经过与导师的讨论,我意识到这可能没有必要:

¥About a week before the coding period began, and after some discussion with my
mentors, I realized that was probably unnecessary:

> “大家好,我们在开会后一直在思考这个项目:考虑到由于依赖,`e/website` 和 `e/lint-roller` 中的提取逻辑处理方式可能有所不同,也许不需要为 API 历史记录单独创建一个包?
>
> ¥"Hi everyone, I was thinking about the project after our huddle: Considering
> that extraction logic will have to be handled differently in `e/website` and
> `e/lint-roller` because of their dependencies, maybe there is no need for a
> separate package for API history stuff?"
>
> | 建议 | 已修订 |
> | :-: | :-: |
> | | |

![proposed][js-proposed]

|

![revised][js-revised]

|

> — Piotr Płaczek(我)通过 Slack
>
> ¥— Piotr Płaczek (me) via Slack

我们最终决定放弃我最初的想法:

¥We ultimately decided to not go ahead with my original idea:

> “@Piotr Płaczek,我觉得没问题!”如果我们发现需要在两个实现之间共享大量代码,我认为我们可以在以后的迭代中将其重构为一个单独的模块 :slightly_smiling_face:"
>
> ¥"@Piotr Płaczek that seems fine to me! I think we can always refactor out to a
> separate module in a later iteration if we find that we need to share a lot of
> code between the two implementations anyways :slightly_smiling_face:"
>
> — Erick Zhao ([@erickzhao][erickzhao]) 通过 Slack
>
> ¥— Erick Zhao ([@erickzhao][erickzhao]) via Slack

我们将这些不同的工具按与它们最相关的方式划分到 Electron 代码库中:

¥Instead, we divided those various tools across the Electron repos that were most
relevant to them:

* `yaml-api-history-schema.json`

* -> `electron/electron` ([`api-history.schema.json`](https://github.com/electron/electron/blob/main/docs/api-history.schema.json))

* `lint-yaml-api-history.ts`

* -> `electron/lint-roller` ([`lint-markdown-api-history.ts`](https://github.com/electron/lint-roller/blob/3d87b7ba8f99868a28648297f31a1587945045ab/bin/lint-markdown-api-history.ts#L4))

* `extract-yaml-api-history.ts`

* -> `electron/website` ([`preprocess-api-history.ts`](https://github.com/electron/website/blob/f7e9446dd7d04b3369e9454f7c95f638fa061f1e/scripts/tasks/preprocess-api-history.ts#L4))

* `yaml-api-history-to-markdown.ts`

* -> `electron/website` ([`transformers/api-history.ts`](https://github.com/electron/website/blob/f7e9446dd7d04b3369e9454f7c95f638fa061f1e/src/transformers/api-history.ts))

* -> `electron/website` ([`ApiHistoryTable.tsx`](https://github.com/electron/website/blob/f7e9446dd7d04b3369e9454f7c95f638fa061f1e/src/components/ApiHistoryTable.tsx))

### Electron 文档网站的 UI 和样式 \{#ui-and-styling-for-electron-documentation-website}

¥UI and styling for Electron documentation website

我最初建议用一个简单的表格来显示 API 历史记录数据:

¥I originally proposed a simple table to display the API History data:

| 设计原型(已关闭) | 设计原型(已打开) |
| :-------: | :-------: |
| | |

![demo1][prototype-closed-proposed]

|

![demo2][prototype-open-proposed]

|

最终实现的设计如下:

¥This is what the final implemented design looks like:

![demo3][open-implemented]

与原型几乎相同。最重要的新增功能是使用 [SemVer](https://semver.org/) 范围,选择该范围是为了更好地传达某个功能存在于哪个版本中(感谢 Samuel Attard [(@MarshallOfSound)](https://github.com/MarshallOfSound) 的建议!)。

¥Pretty much the same as the prototype. The most significant addition is the use
of [SemVer](https://semver.org/) ranges, which were chosen to better communicate
which versions a feature is present in (thanks Samuel Attard
[(@MarshallOfSound)](https://github.com/MarshallOfSound) for the suggestion!).

这一点很重要,因为更改经常会在支持的 Electron 版本之间反向移植,例如,修复可能会被移植到 Electron v32.0.0、v31.1.0 和 v30.2.0 中。这意味着它在 v31.0.0 中不存在,而用户可能会错误地认为它在 v30.x.x 版本中存在。

¥This is important because changes are frequently backported across supported
Electron release lines e.g. a fix may make it into Electron v32.0.0, v31.1.0 and v30.2.0.
This means it is not present in v31.0.0 which a user might mistakenly deduce based
on the fact it is present in a v30.x.x release.

### 使用/样式指南 \{#usagestyle-guide}

¥Usage/style guide

我添加了一个使用/样式指南,专门用于编写新功能的 API 历史记录文档。我详细描述了 YAML 模式的正确用法,并提供了典型/有用的示例等。你可以在 [此处](https://github.com/electron/electron/blob/main/docs/styleguide.md#api-history) 中找到它。

¥I added a usage/style guide dedicated to writing API history documentation for
new features. I described proper usages of the YAML schema in detail, provided
typical/useful examples, etc. You can find it
[here](https://github.com/electron/electron/blob/main/docs/styleguide.md#api-history).

### 迁移指南 \{#migration-guide}

¥Migration guide

由于现有 API 必须迁移到新的文档系统,我创建了一个迁移指南。它涵盖了开发者迁移旧 API 时必须执行的典型步骤:查看重大变更、浏览过往版本、或许还会查看旧的提交等。然后指导开发者遵循使用/样式指南,为每个先前存在的类/函数/等添加 API 历史记录文档。

¥Since existing APIs have to be migrated to the new documentation system, I created
a migration guide. It features the typical steps of what a developer has
to do when migrating old APIs: looking through breaking changes, browsing through
the past releases, maybe looking through old commits, etc.
Then instructing the developer to follow the usage/style guide to add API history
documentation for each previously existing class/function/etc.

遗憾的是,我找不到有效的自动化方法。对于 AI/ML 工程师来说,这可能是一项很棒的任务;然而,我不具备这些技能,而且非常担心会意外将 [hallucinations](https://en.wikipedia.org/wiki/Hallucination_\(artificial_intelligence\)) 引入 API 历史记录。即使是自动化的,最终信息可能仍需要人工验证😕。此任务可能需要手动完成,基于每个文件,[就像在 Node.js 文档中所做的那样](https://github.com/nodejs/node/issues/6578)。

¥Sadly, I couldn't think of a way to automate this effectively. This would probably
be a great task for an AI/ML engineer; however, I don't possess those skills and
was too afraid of accidentally introducing [hallucinations](https://en.wikipedia.org/wiki/Hallucination_\(artificial_intelligence\))
into the API history. Even if automated, the information would still probably have
to be verified by a human in the end 😕. This task will probably have to be done
manually, on a file-by-file basis,
[just like it was done for the Node.js documentation](https://github.com/nodejs/node/issues/6578).

## 可交付成果 \{#deliverables}

¥Deliverables

* `api-history.schema.json`

* 用于记录 API 历史记录的综合 YAML 模式,其中包括对以下内容的支持:

¥A comprehensive YAML schema for documenting API history which includes support
for:

* [x] 添加

¥Additions

* [x] 弃用

¥Deprecations

* [x] 变更

¥Changes

* [x] 指向相关拉取请求的链接

¥Links to relevant pull requests

* [x] 反向移植

¥Backports

* [x] 建议于:[electron/rfc#6][rfc]

¥Proposed in: [electron/rfc#6][rfc]

* [x] 实现/使用于:[electron/electron#42982][electron]

¥Implemented/Used in: [electron/electron#42982][electron]

* [x] 用于:[electron/website#594][website]

¥Used in: [electron/website#594][website]

* `lint-markdown-api-history.ts`

* 用于根据自定义 YAML(技术上为 JSON)模式编写的 YAML API 历史记录进行 linting 的脚本。

¥Script for linting YAML API history written according to a custom YAML
(technically JSON) schema.

* [x] 有用的错误消息

¥Useful error messages

* [x] 全面的文档/代码注释

¥Comprehensive documentation / code comments

* [x] 全面的 ~~Jest~~ Vitest 测试

¥Extensive ~~Jest~~ Vitest tests

* [x] 性能良好

¥Good performance

* [x] 实现于:[electron/lint-roller#73][lint-roller]

¥Implemented in: [electron/lint-roller#73][lint-roller]

* [x] 用于:[electron/electron#42982][electron]

¥Used in: [electron/electron#42982][electron]

* `preprocess-api-history.ts`

* 执行简单验证,以防错误的 API 历史记录进入代码库。此外,由于 [Docusaurus](https://docusaurus.nodejs.cn/) 无法解析 API History 块,因此删除了包含这些块的 HTML 注释标签。

¥Performs simple validation just in case incorrect API History manages to make
it into the repo. Also strips the HTML comment tags that wrap API History blocks
since [Docusaurus](https://docusaurus.nodejs.cn/) cannot parse them.

* [x] 实现/使用于:[electron/website#594][website]

¥Implemented/Used in: [electron/website#594][website]

* `transformers/api-history.ts`

* 用于将 Markdown 文档文件中的 YAML API 历史记录块转换为 ~~Markdown/HTML~~ [React](https://react.nodejs.cn/) 表 (`ApiHistoryTable.tsx`) 的脚本。

¥Script for converting YAML API history blocks in the Markdown documentation files
to ~~Markdown/HTML~~ [React](https://react.nodejs.cn/) tables (`ApiHistoryTable.tsx`).

* [x] 实现/使用于:[electron/website#594][website]

¥Implemented/Used in: [electron/website#594][website]

* `ApiHistoryTable.tsx`

* 用于在文档网站上显示已解析的 API 历史记录数据的 React 表格​​组件。

¥React table component used to display parsed API History data on the
documentation website.

* [x] 使用与网站其他部分设计一致的样式。

¥Uses styling that follows the rest of the website's design.

* [x] 响应迅速、易于访问且编写良好的 HTML、CSS 和 JS。

¥Responsive, accessible, and generally well written HTML, CSS, and JS.

* [x] 实现/使用于:[electron/website#594][website]

¥Implemented/Used in: [electron/website#594][website]

* `styleguide.md`

* 新的 API 历史文档系统的使用/样式指南部分。

¥Usage/style guide section for new API history documentation system.

* [x] 易于理解

¥Easy to understand

* [x] 写得很好

¥Well written

* [x] 包含示例

¥Includes examples

* [x] 实现/使用于:[electron/electron#42982][electron]

¥Implemented/Used in: [electron/electron#42982][electron]

* `api-history-migration-guide.md`

* 新 API 历史文档系统的迁移指南。

¥Migration guide for new API history documentation system.

* [x] 易于理解

¥Easy to understand

* [x] 写得很好

¥Well written

* [x] 包含示例

¥Includes examples

* [x] 实现/使用于:[electron/electron#42982][electron]

¥Implemented/Used in: [electron/electron#42982][electron]

## 结论 \{#conclusion}

¥Conclusion

我很享受开发这个功能的乐趣,并且能够从代码审查和与团队讨论其各种实现细节中积累宝贵的经验。

¥I had a lot of fun working on this feature and was able to earn valuable experience
from code reviews and discussing its various implementation details with the team.

我相信在文档中添加 API 历史记录将使 Electron 开发者的工作更加轻松,尤其是那些试图将现有应用从几年前的 Electron 版本迁移过来的开发者。

¥I believe the addition of API history to the documentation will make the lives of
developers using Electron a lot easier, especially ones attempting to migrate their
existing app from a several year old Electron version.

我还要真诚地感谢我的导师们:

¥I also want to sincerely thank my mentors:

* David Sanders [(@dsanders11)][dsanders11]

* Keeley Hammond [(@VerteDinde)](https://github.com/VerteDinde)

* Erick Zhao [(@erickzhao)][erickzhao]

……以及 Electron 团队的其他成员,感谢他们回答我的问题并花时间对我的拉取请求提供反馈。非常感谢。

¥...and the rest of the Electron team for answering my questions
and taking the time to give me feedback on my pull requests.
It is very much appreciated.

[dsanders11]: https://github.com/dsanders11

[erickzhao]: https://github.com/erickzhao

[js-proposed]: https://github.com/user-attachments/assets/3ec6c87b-1569-443b-8b63-eb20ee4fd96b

[js-revised]: https://github.com/user-attachments/assets/321745a4-ad09-4717-94cc-7b3e08a85d3c

[prototype-closed-proposed]: https://github.com/user-attachments/assets/a1c329d0-9f6b-4079-94d3-f9ff5b80c9ea

[prototype-open-proposed]: https://github.com/user-attachments/assets/f1556d89-8fc8-485f-995c-1edaf8ee1413

[open-implemented]: https://github.com/user-attachments/assets/a8ceb931-ac10-46bc-b747-bf8fd97c839f

[electron]: https://github.com/electron/electron/pull/42982

[website]: https://github.com/electron/website/pull/594

[lint-roller]: https://github.com/electron/lint-roller/pull/73

[rfc]: https://github.com/electron/rfcs/pull/6