1. 术语
本规范依赖于 Infra 标准。[INFRA]
本规范中使用的一些术语定义于 DOM、Fetch、高精度时间、HTML、 IDL、服务工作线程和 URL 标准中。 [DOM] [FETCH] [HR-TIME] [HTML] [WEBIDL] [SERVICE-WORKERS] [URL]
2. 通知
一个 通知 是 一种抽象的 表示,用于描述已发生的事情,例如消息的送达。
一个 通知 具有 一个关联的 服务工作线程注册 (null 或一个 服务工作线程注册)。其初始值为 null。
一个 通知 具有一个关联的 标题 (字符串)。
一个 通知
具有一个关联的
方向 ("auto"、"ltr",
或 "rtl")。
一个 通知 具有一个关联的 语言 (字符串)。
一个 通知 具有一个关联的 正文 (一个 字符串)。
一个 通知 具有一个关联的 导航 URL (null 或一个 URL)。其初始值为 null。
一个 通知 具有一个关联的 标记 (字符串)。
一个 通知
具有一个关联的 时间戳
(一个 EpochTimeStamp)。
时间戳可用于指示一个通知的时间, 即其实际对应的时间。例如,这可以是过去的时间,当通知用于 某条由于设备离线而无法立即送达的消息时, 也可以是未来的时间,用于即将开始的会议。
一个 通知 具有一个关联的 重新通知偏好 (布尔值)。其 初始值为 false。当为 true 时,表示应在以下步骤运行后提醒最终用户: 通知 显示步骤,运行时使用一个新通知,其具有相同的 标记,与某个现有通知一致。
一个 通知 具有一个关联的 静默偏好 (null 或布尔值)。其 初始值为 null。当为 true 时,表示不应发出声音或振动。当为 null 时, 表示是否发出声音或振动应由平台惯例决定。
一个 通知 具有一个关联的 要求交互偏好 (布尔值)。其初始值为 false。当为 true 时,表示在具有足够大的 屏幕的设备上,通知应保持随时可用,直到最终用户激活或忽略 该通知。
一个 通知 可以 具有以下关联的图形: 图像 URL、 图标 URL,以及 徽章 URL;以及它们对应的 图像资源、图标资源,以及 徽章资源。
一个 图像资源 是一张图片,显示为以下对象的 内容的一部分:通知,并应以更高的视觉 优先级显示,高于 图标资源 和 徽章资源,尽管它 可能 只在较少的情形下显示。
一个 图标资源 是用于强化以下内容的图像: 通知 (例如图标,或发送者的照片)。
一个 徽章资源 是一个图标,用于表示 Web 应用程序,或以下 通知 的类别,如果该 Web 应用程序发送多种 类型的 通知。它 可以 用于表示 通知, 当 没有足够的空间显示 通知 本身时。它 也可以 显示在 以下 通知 内部,但此时其视觉优先级应低于 以下 图像资源 和 图标资源。
鼓励开发者不要通过 图像、图标, 或 徽章 传达无法 通过其他方式提供给最终 用户的信息,尤其是因为不支持这些功能的通知平台可能会忽略它们。
一个 通知 具有一组关联的 动作 (一个 列表,包含零个或 多个 通知动作)。一个 通知动作 表示 最终用户的一个选项。每个 通知动作 都具有以下关联项:
- 名称
- 字符串。
- 标题
- 字符串。
- 导航 URL
- null 或一个 URL。其初始值为 null。
- 图标 URL
- null 或一个 URL。其初始值为 null。
- 图标资源
- null 或一个资源。其初始值为 null。
用户可以激活动作,作为激活通知本身的替代方式。 最大 动作数量,其支持的值是一个 由实现定义 的整数,为零 或更大,且受通知平台的限制。
由于动作的显示方式取决于平台,鼓励开发者 确保 最终用户可以从通知中调用的任何动作,在 Web 应用程序中也可用。
某些平台可能会修改 图标资源,以 更好地匹配平台的视觉风格,然后再 将其显示给最终用户,例如将边角改为圆角,或将其绘制为特定 颜色。鼓励开发者使用能够妥善应对此类情况的图标,避免丢失 重要信息,例如由于颜色丢失或边角被裁剪。
一个 非持久化 通知 是一个 通知,其 服务 工作线程注册 为 null。
一个 持久化通知 是一个 通知,
其
服务工作线程注册 非 null。
要 创建通知,使用设置
对象,给定字符串 title、
NotificationOptions
字典 options,以及
环境设置对象 settings:
-
令 origin 为 settings 的 源。
-
令 baseURL 为 settings 的 API 基础 URL。
-
令 fallbackTimestamp 为从 Unix 纪元 到 settings 的 当前挂钟时间 的毫秒数,舍入到 最近的整数。
-
返回以下操作的结果:创建通知,给定 title、 options、origin、baseURL 和 fallbackTimestamp。
要 创建一个
通知,给定字符串 title、
NotificationOptions
字典 options、一个 源
origin、一个 URL baseURL,以及一个 EpochTimeStamp
fallbackTimestamp:
-
令 notification 为一个新的 通知。
-
如果 options["
renotify"] 为 true,并且 options["tag"] 为空字符串,则 抛出 一个TypeError。 -
将 notification 的 数据 设置为 StructuredSerializeForStorage(options["
data"])。 -
将 notification 的 标题 设置为 title。
-
将 notification 的 源 设置为 origin。
-
如果 options["
navigate"] 存在,则 解析 它,使用 baseURL,如果该操作未 返回 failure,则将 notification 的 导航 URL 设置为返回值。(否则 notification 的 导航 URL 保持为 null。) -
如果 options["
image"] 存在,则 解析 它,使用 baseURL,如果该操作未 返回 failure,则将 notification 的 图像 URL 设置为返回值。(否则 notification 的 图像 URL 不设置。) -
如果 options["
icon"] 存在,则 解析 它,使用 baseURL,如果该操作未 返回 failure,则将 notification 的 图标 URL 设置为返回值。(否则 notification 的 图标 URL 不设置。) -
如果 options["
badge"] 存在,则 解析 它,使用 baseURL,如果该操作未 返回 failure,则将 notification 的 徽章 URL 设置为返回值。(否则 notification 的 徽章 URL 不设置。) -
如果 options["
timestamp"] 存在,则将 notification 的 时间戳 设置为该值。否则,将 notification 的 时间戳 设置为 fallbackTimestamp。 -
将 notification 的 要求交互偏好 设置为 options["
requireInteraction"]。 -
将 notification 的 动作 设置为 « »。
-
对于 options["
actions"] 中的每个 entry, 数量不超过 最大动作数量 的支持值 (跳过任何 超出的条目): -
返回 notification。
2.1. 生命周期与 UI 集成
用户代理必须维护一个 通知列表,它是一个 列表,包含零个 或多个 通知。
用户代理应运行 关闭 步骤,针对一个 非持久化通知,在它 被 创建几秒后。
用户代理不应显示 非持久化通知,在 平台的“通知中心”中 (如果有)。
用户代理应保留 持久化通知,直到它们 从以下列表中移除:通知列表。
一个 持久化
通知 可以通过
close()
方法的调用来关闭,该方法属于它的某个 Notification
对象。
用户代理应显示 持久化通知,在平台的 “通知中心”中 (如果有)。
2.2. 权限集成
通知 API 是一个 强大特性,由以下标识:
名称
"notifications"。
[Permissions]
要 获取通知权限状态,运行以下 步骤:
-
令 permissionState 为以下操作的结果:获取当前权限 状态, 使用 "
notifications"。 -
如果 permissionState 为 "
prompt",则返回 "default"。 -
返回 permissionState。
2.3. 方向
本节使用的术语等同于渲染 章节中的术语,该章节属于 HTML。[HTML]
用户代理预期遵循以下文本的 Unicode 语义:
通知 的
标题、正文,以及
标题,属于其每个 动作。每项都
预期在显示时被视为由一个或多个双向算法
段落组成的独立集合,如双向算法的规则 P1、
P2 和 P3 所定义,包括例如支持段落分隔行为,
即 U+000A LINE FEED (LF) 字符的行为。对于以下内容的每个段落:
标题、正文,以及
标题,属于每个 动作,
通知 的
方向 提供
更高层级的覆盖,
覆盖规则 P2 和 P3,条件是其值不为 "auto"。[BIDI]
该 通知 的 方向 也决定相对 顺序,即以下 通知 的 动作 应显示的顺序, 向最终用户显示时,如果通知平台将它们并排显示。
2.4. 语言
该 通知 的 语言 指定主要语言, 用于该 通知 的 标题、正文 以及 以下 标题,属于其每个 动作。其值是一个 字符串。空字符串表示主要语言未知。任何其他字符串都必须 被解释为语言标签。不强制要求其有效或格式良好。[BCP47]
鼓励开发者仅使用有效的语言标签。
2.5. 资源
获取步骤,给定 一个 通知 notification 和 null 或 一个 环境设置对象 settings,如下:
-
如果通知平台支持图像,并且 notification 的 图像 URL 已设置,则 获取通知资源,给定 notification、notification 的 图像 URL、 settings,以及以下步骤,给定资源 resource:将 notification 的 图像资源 设置为 resource。
-
如果通知平台支持图标,并且 notification 的 图标 URL 已设置,则 获取通知资源,给定 notification、notification 的 图标 URL、 settings,以及以下步骤,给定资源 resource:将 notification 的 图标资源 设置为 resource。
-
如果通知平台支持徽章,并且 notification 的 徽章 URL 已设置,则 获取通知资源,给定 notification、notification 的 徽章 URL、 settings,以及以下步骤,给定资源 resource:将 notification 的 徽章资源 设置为 resource。
-
如果通知平台支持动作和动作图标,则 对于每个 action,属于 notification 的 动作:如果 action 的 图标 URL 非 null,则 获取通知资源,给定 notification、 action 的 图标 URL、settings,以及 以下步骤,给定资源 resource:将 action 的 图标 资源 设置为 resource。
要 获取一个 通知资源,给定一个 通知 notification、一个 URL url、null 或一个 环境设置对象 settings,以及 一个算法 processResource,它接受一个资源:
-
令 request 为一个新的 请求,其 URL 为 url,客户端 为 settings,目标 为 "
image",模式 为 "no-cors",并且 凭据模式 为 "include"。 -
如果 settings 为 null,则将 request 的 源 设置为 notification 的 源,将 request 的 引用来源 设置为 "
no-referrer",并将 request 的 服务工作线程模式 设置为 "none"。当用户代理显示以下通知时,就属于这种情况: 声明式推送 消息的通知。这种通知的资源在获取时不涉及 服务工作线程,因为声明式推送消息 被设计为不需要服务工作线程。 [PUSH-API]
-
获取 request,将 useParallelQueue 设置为 true, 并将 processResponseConsumeBody 设置为 以下步骤,给定一个 响应 response,以及 null、failure 或一个 字节序列 bytes:
-
如果 bytes 为 null 或 failure,则返回。
-
尝试将 bytes 解码为图像。
-
如果支持该图像格式,则运行 processResource,给定解码后的 资源。
-
2.6. 显示通知
通知 显示步骤,给定一个 通知 notification,以及 null 或一个 环境设置对象 settings, 如下:
-
运行 获取步骤, 给定 notification 和 settings。
-
等待所有 获取操作 完成,并等待 notification 的 图像资源、 图标资源,以及 徽章资源 设置完毕 (如果有),以及以下 图标 资源,用于 notification 的 动作 (如果有)。
-
令 shown 为 false。
-
令 oldNotification 为以下 通知,位于 通知 列表 中,其 标记 不是空字符串,且等于 notification 的 标记,并且 其 源 同源 于 notification 的 源,如果存在, 否则为 null 。
-
如果 oldNotification 非 null:
-
如果 shown 为 false:
-
如果 shown 为 false,或者 oldNotification 非 null,且 notification 的 重新通知偏好 为 true,则可以选择 以用户代理定义的方式提醒最终用户 (例如,播放声音)。
-
如果 notification 是一个 非持久化通知,则 将一个任务入队, 以 触发一个事件,名称为
show,目标为Notification对象,该对象表示 notification。
2.7. 激活通知
当一个 通知 notification,或其某个 动作 被最终用户激活时, 假设底层通知 平台支持激活,用户代理必须 (除非另有规定) 运行以下步骤:
-
令 action 为 null。
-
令 navigationURL 为 notification 的 导航 URL。
-
如果 action 非 null,则将 navigationURL 设置为 action 的 导航 URL。
这是有意如此设计的,使得当一个 通知动作 的 导航 URL 为 null 时,它会 继续执行到
click事件,为 Web 开发者提供更大的灵活性。 -
如果 navigationURL 非 null:
-
从以下两个选项中选择一个,以 由实现定义 的方式:
-
创建一个全新的顶层 可遍历对象,给定 navigationURL。
强烈鼓励用户代理遵循平台 惯例。
-
返回。
-
-
如果 notification 是一个 持久化通知:
-
令 actionName 为空字符串。
-
如果 action 非 null,则将 actionName 设置为 action 的 名称。
- 触发一个服务工作线程通知
事件,名称为 "
notificationclick",给定 notification 和 actionName。
-
-
否则,将一个任务入队,以运行以下步骤:
-
令 intoFocus 为以下操作的结果:触发一个事件,名称为
click,目标为Notification对象,该对象表示 notification,其cancelable属性初始化为 true。鼓励用户代理使
focus()能够在事件 监听器内部起作用,该监听器监听名为click的事件。 -
如果 intoFocus 为 true,则用户代理应使 notification 相关的 浏览上下文 的视口获得焦点。
-
在整个 Web 平台中,“激活”被有意误称为“点击”。
2.8. 关闭通知
当一个 通知 被关闭时,无论是由底层通知 平台还是由 最终用户关闭,其 关闭步骤 都必须运行。
关闭步骤,针对一个 给定的 通知 notification,如下:
要 处理关闭 事件,给定一个 通知 notification:
-
如果 notification 是一个 持久化通知,并且 notification 被最终用户关闭,则 触发一个服务工作线程通知 事件,名称为 "
notificationclose",给定 notification。 -
如果 notification 是一个 非持久化通知,则 将一个任务入队, 以 触发一个事件,名称为
close,目标为Notification对象,该对象表示 notification。
3. API
[Exposed =(Window ,Worker )]interface :Notification EventTarget {constructor (DOMString ,title optional NotificationOptions = {});options static readonly attribute NotificationPermission permission ; [Exposed =Window ]static Promise <NotificationPermission >requestPermission (optional NotificationPermissionCallback );deprecatedCallback static readonly attribute unsigned long maxActions ;attribute EventHandler onclick ;attribute EventHandler onshow ;attribute EventHandler onerror ;attribute EventHandler onclose ;readonly attribute DOMString title ;readonly attribute NotificationDirection dir ;readonly attribute DOMString lang ;readonly attribute DOMString body ;readonly attribute USVString navigate ;readonly attribute DOMString tag ;readonly attribute USVString image ;readonly attribute USVString icon ;readonly attribute USVString badge ;readonly attribute EpochTimeStamp timestamp ;readonly attribute boolean renotify ;readonly attribute boolean ?silent ;readonly attribute boolean requireInteraction ; [SameObject ]readonly attribute any data ; [SameObject ]readonly attribute FrozenArray <NotificationAction >actions ;undefined close (); };dictionary {NotificationOptions NotificationDirection = "auto";dir DOMString = "";lang DOMString = "";body USVString ;navigate DOMString = "";tag USVString ;image USVString ;icon USVString ;badge EpochTimeStamp ;timestamp boolean =renotify false ;boolean ?=silent null ;boolean =requireInteraction false ;any =data null ;sequence <NotificationAction >= []; };actions enum {NotificationPermission ,"default" ,"denied" };"granted" enum {NotificationDirection ,"auto" ,"ltr" };"rtl" dictionary {NotificationAction required DOMString ;action required DOMString ;title USVString ;navigate USVString ; };icon callback =NotificationPermissionCallback undefined (NotificationPermission );permission
一个 非持久化通知 由一个 Notification
对象表示,并可通过以下方式创建:Notification
的
构造函数。
一个 持久化
通知 由零个或多个
Notification
对象表示,并可通过以下
showNotification()
方法创建。
3.1. 垃圾回收
一个 Notification
对象不得被垃圾回收,如果 通知列表
包含
其对应的 通知,并且它具有一个
事件监听器,其 type 为 click、
show、
close,或 error。
3.2. 构造函数
该
new Notification(title, options)
构造函数的步骤如下:
3.3. 静态成员
静态 permission 获取器的步骤是
返回以下操作的结果:获取通知权限状态。
如果你编写标准,请不要照搬上述内容。同步权限就像 同步 IO,是个糟糕的主意。
鼓励开发者使用权限 API 的 query()
方法
来代替。[Permissions]
const permission = await navigator.permissions.query({name: "notifications"}); if (permission.state === "granted") { // 我们已获准使用此 API… }
静态
requestPermission(deprecatedCallback)
方法的步骤如下:
-
令 global 为 当前全局对象。
-
令 promise 为 一个新的 promise,位于 this 的 相关 Realm 中。
-
运行以下步骤,并行 执行:
-
返回 promise。
通知是迄今为止唯一一个事先询问最终用户 合理的场景。其他 API 的规范不应使用这种模式,而应采用 许多更合适的 替代方案 之一。
静态 maxActions 获取器的步骤是
返回 最大动作数量 的支持值。
3.4. 对象成员
以下是 事件处理器 (及其对应的
事件处理器事件类型),必须作为
属性受到以下
Notification
对象的支持。
| 事件处理器 | 事件处理器事件类型 |
|---|---|
onclick
| click
|
onshow
| show
|
onerror
| error
|
onclose
| close
|
close() 方法的步骤是运行
关闭步骤,针对 this 的 通知。
title 获取器的步骤是返回
this 的 通知 的
标题。
lang 获取器的步骤是返回
this 的 通知 的
语言。
body 获取器的步骤是返回
this 的 通知 的
正文。
navigate 获取器的步骤如下:
image 获取器的步骤如下:
icon 获取器的步骤如下:
badge 获取器的步骤如下:
timestamp 获取器的步骤是返回
this 的 通知 的
时间戳。
renotify 获取器的步骤是返回
this 的 通知 的
重新通知
偏好。
silent 获取器的步骤是返回
this 的 通知 的
静默
偏好。
requireInteraction 获取器的步骤是
返回 this 的 通知 的
要求交互偏好。
data 获取器的步骤是返回
StructuredDeserialize(this 的 通知 的
数据, this 的 相关 Realm)。如果此操作抛出异常,
则返回 null。
actions 获取器的步骤如下:
-
令 frozenActions 为一个空列表,其类型为
NotificationAction。 -
-
令 action 为一个新的
NotificationAction。 -
如果 entry 的 导航 URL 非 null,则 将 action["
navigate"] 设置为 entry 的 导航 URL,序列化后 的结果。 -
如果 entry 的 图标 URL 非 null,则将 action["
icon"] 设置为 entry 的 图标 URL, 序列化后 的结果。 -
调用 Object.freeze,作用于 action,以 防止脚本意外修改它。
-
将 action 追加到 frozenActions。
-
-
返回以下操作的结果:创建冻结数组,使用 frozenActions。
3.5. 示例
3.5.1. 使用来自页面的事件
非持久化的 Notification
对象在其生命周期中派发事件,开发者可以使用这些事件来
实现期望的行为。
click 事件在最终用户激活通知时派发。
var not = new Notification("Paul Kalkbrenner 的 Gebrünn Gebrünn", { icon: "newsong.svg", tag: "song" });
not.onclick = function() { displaySong(this); };
3.5.2. 使用来自服务工作线程的动作
持久化
通知 触发
notificationclick 事件,目标为 ServiceWorkerGlobalScope。
这里,一个服务工作线程显示一条通知,带有一个“归档” 通知动作,允许最终用户 直接从 通知执行这一常见任务,而不必打开网站 (例如,通知平台可能在 通知上显示一个按钮)。最终用户也可以激活通知的主体,以 打开收件箱。
self.registration.showNotification("来自 Alice 的新邮件", {
actions: [{action: 'archive', title: "归档"}]
});
self.addEventListener('notificationclick', function(event) {
event.notification.close();
if (event.action === 'archive') {
silentlyArchiveEmail();
} else {
clients.openWindow("/inbox");
}
}, false);
3.5.3. 使用 tag 成员处理多个实例
Web 应用程序经常在多个实例中并发运行,例如最终用户
在多个浏览器标签页中打开邮件应用程序时。由于桌面是共享资源,
通知 API 为这些实例提供了一种轻松协调的方式,即使用
tag 成员。
表示同一个概念事件的通知可以使用相同的标记,而当 两条通知都显示时,最终用户只会收到一条通知。
实例 1 | 实例 2
|
// 实例注意到有新邮件。 |
new Notification("来自 John Doe 的新邮件", |
{ tag: 'message1' }); |
|
| // 稍后,此实例注意到
| // 有新邮件。
| new Notification("来自 John Doe 的新邮件",
| { tag: 'message1' });
这种情况下,如果用户代理遵循这里的算法,结果是 仅有一条 通知“来自 John Doe 的新邮件”。
3.5.4. 使用 tag 成员处理单个
实例
tag 成员也可以由
应用程序的单个实例使用,以便在状态变化时尽可能保持通知为最新状态。
例如,如果 Alice 正在使用聊天应用程序与 Bob 聊天,而 Bob 在 Alice 空闲期间发送了多条消息,应用程序可能希望 Alice 不会 为每条消息都看到一条桌面通知。
// Bob 说 "嗨"
new Notification("Bob: 嗨", { tag: 'chat_Bob' });
// Bob 说 "你今天下午有空吗?"
new Notification("Bob: 嗨 / 你今天下午有空吗?", { tag: 'chat_Bob' });
这种情况的结果是 仅有一条 通知;第二条
替换具有相同标记的第一条。在将通知排队的平台上
(先进先出),使用标记还能让通知保持其
在队列中的位置。在优先显示最新通知的平台上,
可以通过以下 close()
方法实现类似的结果。
4. 服务工作线程 API
dictionary {GetNotificationOptions DOMString = ""; };tag partial interface ServiceWorkerRegistration {Promise <undefined >showNotification (DOMString ,title optional NotificationOptions = {});options Promise <sequence <Notification >>getNotifications (optional GetNotificationOptions = {}); }; [filter Exposed =ServiceWorker ]interface :NotificationEvent ExtendableEvent {(constructor DOMString ,type NotificationEventInit );eventInitDict readonly attribute Notification notification ;readonly attribute DOMString action ; };dictionary :NotificationEventInit ExtendableEventInit {required Notification ;notification DOMString = ""; };action partial interface ServiceWorkerGlobalScope {attribute EventHandler onnotificationclick ;attribute EventHandler onnotificationclose ; };
一个 服务工作线程注册 具有一个关联的
是否
showNotification() 已被成功调用
(一个 布尔值),
其初始值为 false。
这是为 推送 API 标准提供的基础设施。[PUSH-API]
该
showNotification(title, options)
方法的步骤如下:
该
getNotifications(filter)
方法的步骤如下:
-
令 promise 为 一个新的 promise,位于 realm 中。
-
运行以下步骤,并行 执行:
-
返回 promise。
此方法返回零个或多个新的 Notification
对象,它们可能表示
相同的底层 通知,与以下 Notification
已有对象所表示的通知相同。
要 触发一个服务工作线程通知事件,名称为
name,给定一个
通知
notification,以及一个可选字符串
action (默认为
空字符串):运行 触发功能事件,给定 name、NotificationEvent、
notification 的 服务工作线程注册,以及以下
初始化项:
notification- 一个新的
Notification对象,表示 notification。 action- action
notification 获取器的步骤
是
返回其初始化时的值。
action 获取器的步骤是返回
其
初始化时的值。
以下是 事件处理器 (及其对应的
事件处理器事件类型),必须作为属性受到
以下
ServiceWorkerGlobalScope
对象的支持:
| 事件处理器 | 事件处理器事件类型 |
|---|---|
onnotificationclick
| notificationclick
|
onnotificationclose
| notificationclose
|
致谢
感谢 Addison Phillips, Aharon (Vladimir) Lanin, Alex Russell, Anssi Kostiainen, Arkadiusz Michalski, Boris Zbarsky, Brady Eidson, David Håsäther, Doug Turner, Drew Wilson, Ehsan Akhgari, Frederick Hirsch, Ian Hickson, Jake Archibald, James Graham, John Mellor, Jon Lee, Jonas Sicking, Kagami Sascha Rosylight, Leo Tenenbaum, Michael Cooper, Michael Henretty, Michael™ Smith, Michael van Ouwerkerk, Mike Taylor, Nicolás Satragno, Olli Pettay, Peter Beverloo, Philip Jägenstedt, Reuben Morais, Rich Tibbett, Robert Bindar, 박상현 (Sanghyun Park), Simon Pieters, Theresa O’Connor, timeless,以及 triple-underscore 的出色表现。
本标准由 Anne van Kesteren 编写 (Apple, annevk@annevk.nl)。 早期版本由 John Gregg 编写 (Google, johnnyg@google.com)。
知识产权
版权所有 © WHATWG (Apple, Google, Mozilla, Microsoft)。本作品依据 知识共享署名 4.0 国际许可协议 授权。若本作品的部分内容被纳入源代码,此类 源代码中的部分则依据 BSD 3 条款许可证 授权。
这是现行标准。对于 希望查看专利审查版本的读者,请参阅 现行标准审查草案。