1. URL 模式
1.1. 介绍
一个 URL 模式 由多个 组件 组成,每个组件代表一个可以与 URL 的对应组件匹配的 模式。
它可以通过为每个组件提供字符串或通过简写字符串构造。它还可以选择相对于基 URL 进行解析。
简写 "https://example.com/:category/*
" 对应以下组件:
它匹配以下 URL:
-
https://example.com/products/
-
https://example.com/blog/our-greatest-product-ever
它不匹配以下 URL:
-
https://example.com/
-
http://example.com/products/
-
https://example.com:8443/blog/our-greatest-product-ever
这是一个相对简单的模式,要求大多数组件要么匹配一个确切的字符串,要么允许任意字符串 ("*
")。路径名组件 匹配具有至少两个 /
分隔的路径组件的路径,其中第一个被捕获为 "category
"。
简写 "http{s}?://{:subdomain.}?shop.example/products/:id([0-9]+)#reviews
" 对应以下组件:
- 协议
- "
http{s}?
" - 用户名
- "
*
" - 密码
- "
*
" - 主机名
- "
{:subdomain.}?shop.example
" - 端口
- ""
- 路径名
- "
/products/:id([0-9]+)
" - 查询
- ""
- 哈希
- "
reviews
"
它匹配以下 URL:
-
https://shop.example/products/74205#reviews
-
https://kathryn@voyager.shop.example/products/74656#reviews
-
http://insecure.shop.example/products/1701#reviews
它不匹配以下 URL:
-
https://shop.example/products/2000
-
http://shop.example:8080/products/0#reviews
-
https://nx.shop.example/products/01?speed=5#reviews
-
https://shop.example/products/chair#reviews
这是一个更复杂的模式,包含:
简写 "../admin/*
" 和基 URL "https://discussion.example/forum/?page=2
" 对应以下组件:
它匹配以下 URL:
-
https://discussion.example/admin/
-
https://edd:librarian@discussion.example/admin/update?id=1
它不匹配以下 URL:
-
https://discussion.example/forum/admin/
-
http://discussion.example:8080/admin/update?id=1
此模式展示了路径名如何相对于基 URL 进行解析,类似于相对 URL 的解析方式。
1.2. URLPattern
类
typedef (USVString or URLPatternInit ); [
URLPatternInput Exposed =(Window ,Worker )]interface {
URLPattern constructor (URLPatternInput ,
input USVString ,
baseURL optional URLPatternOptions = {});
options constructor (optional URLPatternInput = {},
input optional URLPatternOptions = {});
options boolean test (optional URLPatternInput = {},
input optional USVString );
baseURL URLPatternResult ?exec (optional URLPatternInput = {},
input optional USVString );
baseURL readonly attribute USVString protocol ;readonly attribute USVString username ;readonly attribute USVString password ;readonly attribute USVString hostname ;readonly attribute USVString port ;readonly attribute USVString pathname ;readonly attribute USVString search ;readonly attribute USVString hash ;readonly attribute boolean hasRegExpGroups ; };dictionary {
URLPatternInit USVString ;
protocol USVString ;
username USVString ;
password USVString ;
hostname USVString ;
port USVString ;
pathname USVString ;
search USVString ;
hash USVString ; };
baseURL dictionary {
URLPatternOptions boolean =
ignoreCase false ; };dictionary {
URLPatternResult sequence <URLPatternInput >;
inputs URLPatternComponentResult ;
protocol URLPatternComponentResult ;
username URLPatternComponentResult ;
password URLPatternComponentResult ;
hostname URLPatternComponentResult ;
port URLPatternComponentResult ;
pathname URLPatternComponentResult ;
search URLPatternComponentResult ; };
hash dictionary {
URLPatternComponentResult USVString ;
input record <USVString , (USVString or undefined )>; };
groups
每个 URLPattern
都有一个关联的URL模式,一个 URL模式。
urlPattern = new
URLPattern
(input)- 构建一个新的
URLPattern
对象。input 是一个包含每个URL组件(如主机名、路径名等)的分离模式的对象。缺失的组件将默认为通配符模式。此外,input 可以包含一个baseURL
属性,该属性为任何缺失的组件提供静态文本模式。 urlPattern = new
URLPattern
(patternString, baseURL)- 构建一个新的
URLPattern
对象。patternString 是一个包含一个或多个组件的模式语法的URL字符串。如果提供了 baseURL,那么 patternString 可以是相对的。此构造函数始终至少设置一个空字符串值,并且不将任何组件默认为通配符模式。 urlPattern = new
URLPattern
(input, options)- 构建一个新的
URLPattern
对象。options 是一个包含其他配置选项的对象,这些选项可以影响组件的匹配方式。目前它只有一个属性ignoreCase
,可以设置为 true 以启用不区分大小写的匹配。请注意,默认情况下(即在没有 options 参数的情况下),匹配总是区分大小写的。
urlPattern = new
URLPattern
(patternString, baseURL, options)- 构建一个新的
URLPattern
对象。这支持一个URLPatternOptions
对象,当从 patternString 对象构造模式时,用来描述各个组件的模式以及基本URL。 matches = urlPattern.
test
(input)- 测试 urlPattern 是否匹配给定的参数。input 是一个包含表示每个URL组件的字符串的对象;例如主机名、路径名等。缺失的组件被视为空字符串。此外,input 可以包含一个
baseURL
属性,该属性为任何缺失的组件提供值。如果 urlPattern 按照组件逐一匹配 input,则返回 true。否则,返回 false。 matches = urlPattern.
test
(url, baseURL)- 测试 urlPattern 是否匹配给定的参数。url 是一个URL字符串。如果提供了 baseURL,那么 url 可以是相对的。
如果 urlPattern 按照组件逐一匹配 input,则返回 true。否则,返回 false。
result = urlPattern.
exec
(input)- 根据给定的参数执行 urlPattern。input 是一个包含表示每个URL组件的字符串的对象;例如主机名、路径名等。缺失的组件被视为空字符串。此外,input 可以包含一个 baseURL 属性,为任何缺失的组件提供值。
如果 urlPattern 按照组件逐一匹配 input,则返回一个包含结果的对象。匹配的组值包含在 result 对象内的各组件组对象中;例如
matches.pathname.groups.id
。如果 urlPattern 不匹配 input,则 result 为 null。 result = urlPattern.
exec
(url, baseURL)- 根据给定的参数执行 urlPattern。url 是一个URL字符串。如果提供了 baseURL,那么 input 可以是相对的。
如果 urlPattern 按照组件逐一匹配 input,则返回一个包含结果的对象。匹配的组值包含在 result 对象内的各组件组对象中;例如
matches.pathname.groups.id
。如果 urlPattern 不匹配 input,则 result 为 null。 urlPattern.
protocol
-
返回 urlPattern 的规范化协议模式字符串。
urlPattern.
username
-
返回 urlPattern 的规范化用户名模式字符串。
urlPattern.
password
-
返回 urlPattern 的规范化密码模式字符串。
urlPattern.
hostname
-
返回 urlPattern 的规范化主机名模式字符串。
urlPattern.
port
-
返回 urlPattern 的规范化端口模式字符串。
urlPattern.
pathname
-
返回 urlPattern 的规范化路径名模式字符串。
urlPattern.
search
-
返回 urlPattern 的规范化搜索模式字符串。
urlPattern.
hash
-
返回 urlPattern 的规范化哈希模式字符串。
urlPattern.
hasRegExpGroups
-
返回 urlPattern 是否包含一个或多个使用正则表达式匹配的组。
new URLPattern(input, baseURL, options)
构造函数步骤为:
-
运行 initialize,给定 this,input,baseURL,以及 options。
new URLPattern(input, options)
构造函数步骤为:
-
运行 initialize,给定 this,input,null,以及 options。
URLPattern
给定一个 URLPattern
this,URLPatternInput
input,字符串或 null baseURL,以及 URLPatternOptions
options:
-
将 this 的 关联的URL模式 设置为根据 input,baseURL 和 options 生成的结果。
test(input, baseURL)
方法步骤为:
1.3. URL 模式结构体
1.4. 高级操作
URLPatternInput
input、字符串或空值 baseURL 和 URLPatternOptions
options,创建一个 URL 模式:
-
将 init 设为 null。
-
如果 input 是一个 标量值字符串,则:
-
否则:
-
断言:input 是
URLPatternInit
。 -
如果 baseURL 不为 null,则抛出一个
TypeError
。 -
将 init 设置为 input。
-
-
将 processedInit 设置为 处理 URLPatternInit 的结果,并给定 init、"
pattern
"、null、null、null、null、null、null、null 和 null。 -
对每个 « "
protocol
", "username
", "password
", "hostname
", "port
", "pathname
", "search
", "hash
" » 的 componentName: -
如果 processedInit["
protocol
"] 是一个 特殊方案,且 processedInit["port
"] 是一个表示其对应 默认端口 的字符串,使用 ASCII 数字 表示,则将 processedInit["port
"] 设置为空字符串。 -
将 urlPattern 设为一个新的 URL 模式。
-
将 urlPattern 的 协议组件 设置为 编译组件 的结果,给定 processedInit["
protocol
"],规范化协议 和 默认选项。 -
将 urlPattern 的 用户名组件 设置为 编译组件 的结果,给定 processedInit["
username
"],规范化用户名 和 默认选项。 -
将 urlPattern 的 密码组件 设置为 编译组件 的结果,给定 processedInit["
password
"],规范化密码 和 默认选项。 -
如果运行 主机名模式是 IPv6 地址 的结果,给定 processedInit["
hostname
"] 为真,则将 urlPattern 的 主机名组件 设置为 编译组件 的结果,给定 processedInit["hostname
"],规范化 IPv6 主机名 和 主机名选项。 -
否则,将 urlPattern 的 主机名组件 设置为 编译组件 的结果,给定 processedInit["
hostname
"],规范化主机名 和 主机名选项。 -
将 urlPattern 的 端口组件 设置为 编译组件 的结果,给定 processedInit["
port
"],规范化端口 和 默认选项。 -
将 compileOptions 设置为 默认选项 的副本,忽略大小写 属性设置为 options["
ignoreCase
"]。 -
如果运行 协议组件匹配特殊方案 的结果为真,给定 urlPattern 的 协议组件,则:
-
否则,将 urlPattern 的 路径名组件 设置为 编译组件 的结果,给定 processedInit["
pathname
"],规范化不透明路径名 和 compileOptions。 -
将 urlPattern 的 查询组件 设置为 编译组件 的结果,给定 processedInit["
search
"],规范化查询 和 compileOptions。 -
将 urlPattern 的 哈希组件 设置为 编译组件 的结果,给定 processedInit["
hash
"],规范化哈希 和 compileOptions。 -
返回 urlPattern。
URLPatternInput
或 URL input,以及一个可选的字符串 baseURLString:
-
将 protocol 设为空字符串。
-
将 username 设为空字符串。
-
将 password 设为空字符串。
-
将 hostname 设为空字符串。
-
将 port 设为空字符串。
-
将 pathname 设为空字符串。
-
将 search 设为空字符串。
-
将 hash 设为空字符串。
-
将 inputs 设为空 列表。
-
将 input 添加到 inputs 中。
-
如果 input 是
URLPatternInit
,则:-
如果提供了 baseURLString,则抛出
TypeError
。 -
将 applyResult 设为 处理 URLPatternInit 的结果,给定 input、"url"、protocol、username、password、hostname、port、pathname、search 和 hash。如果抛出异常,捕获并返回 null。
-
将 protocol 设为 applyResult["
protocol
"]。 -
将 username 设为 applyResult["
username
"]。 -
将 password 设为 applyResult["
password
"]。 -
将 hostname 设为 applyResult["
hostname
"]。 -
将 port 设为 applyResult["
port
"]。 -
将 pathname 设为 applyResult["
pathname
"]。 -
将 search 设为 applyResult["
search
"]。 -
将 hash 设为 applyResult["
hash
"]。
-
-
否则:
-
将 protocolExecResult 设为 RegExpBuiltinExec(urlPattern 的 协议组件 的 正则表达式,protocol)。
-
将 usernameExecResult 设为 RegExpBuiltinExec(urlPattern 的 用户名组件 的 正则表达式,username)。
-
将 passwordExecResult 设为 RegExpBuiltinExec(urlPattern 的 密码组件 的 正则表达式,password)。
-
将 hostnameExecResult 设为 RegExpBuiltinExec(urlPattern 的 主机名组件 的 正则表达式,hostname)。
-
将 portExecResult 设为 RegExpBuiltinExec(urlPattern 的 端口组件 的 正则表达式,port)。
-
将 pathnameExecResult 设为 RegExpBuiltinExec(urlPattern 的 路径名组件 的 正则表达式,pathname)。
-
将 searchExecResult 设为 RegExpBuiltinExec(urlPattern 的 查询组件 的 正则表达式,search)。
-
将 hashExecResult 设为 RegExpBuiltinExec(urlPattern 的 哈希组件 的 正则表达式,hash)。
-
如果 protocolExecResult、usernameExecResult、passwordExecResult、hostnameExecResult、portExecResult、pathnameExecResult、searchExecResult 或 hashExecResult 为 null,则返回 null。
-
将 result 设为一个新的
URLPatternResult
。 -
将 result["
inputs
"] 设置为 inputs。 -
将 result["
protocol
"] 设置为 创建组件匹配结果 的结果,给定 urlPattern 的 协议组件、protocol 和 protocolExecResult。 -
将 result["
username
"] 设置为 创建组件匹配结果 的结果,给定 urlPattern 的 用户名组件、username 和 usernameExecResult。 -
将 result["
password
"] 设置为 创建组件匹配结果 的结果,给定 urlPattern 的 密码组件、password 和 passwordExecResult。 -
将 result["
hostname
"] 设置为 创建组件匹配结果 的结果,给定 urlPattern 的 主机名组件、hostname 和 hostnameExecResult。 -
将 result["
port
"] 设置为 创建组件匹配结果 的结果,给定 urlPattern 的 端口组件、port 和 portExecResult。 -
将 result["
pathname
"] 设置为 创建组件匹配结果 的结果,给定 urlPattern 的 路径名组件、pathname 和 pathnameExecResult。 -
将 result["
search
"] 设置为 创建组件匹配结果 的结果,给定 urlPattern 的 查询组件、search 和 searchExecResult。 -
将 result["
hash
"] 设置为 创建组件匹配结果 的结果,给定 urlPattern 的 哈希组件、hash 和 hashExecResult。 -
返回 result。
-
返回 false。
1.5. 内部结构
-
将 part list 设为运行 解析模式字符串 的结果,给定 input、options 和 encoding callback。
-
将 (regular expression string, name list) 设为运行 生成正则表达式和名称列表 的结果,给定 part list 和 options。
-
将 flags 设为空字符串。
-
如果 options 的 忽略大小写 为 true,则将 flags 设为 "
vi
"。 -
否则将 flags 设为 "
v
" -
将 regular expression 设为 RegExpCreate(regular expression string, flags)。如果抛出异常,捕获它并抛出
TypeError
。该规范使用正则表达式执行所有匹配,但这不是强制性的。实现可以在可能的情况下直接对 部分列表 进行匹配;例如,当没有自定义正则表达式匹配组时。然而,如果存在自定义正则表达式,则必须立即在 编译组件 算法中评估它们,以便在它们无效时抛出错误。
-
将 pattern string 设为运行 生成模式字符串 的结果,给定 part list 和 options。
-
将 has regexp groups 设为 false。
-
遍历 part list 中的每个 part:
-
返回一个新的 组件,其 模式字符串 为 pattern string,正则表达式 为 regular expression,组名称列表 为 name list,且 具有正则表达式组 为 has regexp groups。
-
将 result 设为一个新的
URLPatternComponentResult
。 -
将 result["
input
"] 设为 input。 -
将 index 设为 1。
-
当 index 小于 获取(execResult, "
length
") 时: -
将 result["
groups
"] 设为 groups。 -
返回 result。
默认选项 是一个 选项 结构,其中 分隔符代码点 设为空字符串,前缀代码点 也设为空字符串。
主机名选项 是一个 选项 结构,其中 分隔符代码点 设为 ".
",前缀代码点 设为空字符串。
路径名选项 是一个 选项 结构,其中 分隔符代码点 设为 "/
",前缀代码点 设为 "/
"。
-
遍历 special scheme list 中的每个 scheme:
-
将 test result 设为 RegExpBuiltinExec(protocol component 的 正则表达式,scheme)。
-
如果 test result 不为 null,则返回 true。
-
-
返回 false。
1.6. 构造器字符串解析
构造器字符串解析器 是一个 结构。
一个 构造器字符串解析器 具有一个关联的 输入,这是一个字符串,必须在创建时设置。
一个 构造器字符串解析器 具有一个关联的 token 列表,一个 token 列表,必须在创建时设置。
一个 构造器字符串解析器 具有一个关联的 结果,一个 URLPatternInit
,最初设置为一个新的 URLPatternInit
。
一个 构造器字符串解析器 具有一个关联的 组件开始,一个数字,最初设置为 0。
一个 构造器字符串解析器 具有一个关联的 token 索引,一个数字,最初设置为 0。
一个 构造器字符串解析器 具有一个关联的 token 增量,一个数字,最初设置为 1。
一个 构造器字符串解析器 具有一个关联的 组深度,一个数字,最初设置为 0。
一个 构造器字符串解析器 具有一个关联的 主机名 IPv6 括号深度,一个数字,最初设置为 0。
一个 构造器字符串解析器 具有一个关联的 协议匹配特殊方案标志,一个布尔值,最初设置为 false。
一个 构造器字符串解析器 具有一个关联的 状态,一个字符串,最初设置为 "init
"。它必须是以下之一:
- "
init
" - "
protocol
" - "
authority
" - "
username
" - "
password
" - "
hostname
" - "
port
" - "
pathname
" - "
search
" - "
hash
" - "
done
"
URLPattern 构造器字符串算法与 基本 URL 解析器 算法非常相似,但有一些差异使我们无法直接使用该算法。
首先,URLPattern 构造器字符串解析器基于使用 "lenient
" tokenize 策略 生成的 token 操作。相比之下,基本 URL 解析器 基于码点操作。使用 token 允许 URLPattern 构造器字符串解析器更容易区分模式语法中重要的码点和可能是 URL 组件分隔符的码点。例如,它可以轻松处理 "https://a.c:hmm.example.com:8080
" 中的命名组 ":hmm
",而不会与端口号混淆。
其次,URLPattern 构造器字符串解析器需要避免像 基本 URL 解析器 那样对所有码点应用 URL 规范化。相反,我们只对模式字符串中我们知道安全的部分执行规范化操作,这些部分会在编译每个组件模式字符串时进行处理。
最后,URLPattern 构造器字符串解析器不处理 基本 URL 解析器 状态机的某些部分。例如,它不会特别处理反斜杠,因为它们将被视为模式字符,并且需要大量转义。此外,该解析器可能无法处理某些更复杂的 URL 解析算法,例如带有主机名的文件 URL。这种解析器的目标是处理最常见的 URL,同时允许通过 URLPatternInit
构造器处理任何特定情况。
在构造器字符串算法中,如果指定了较早的组件但没有指定较晚的组件,则通配路径名、搜索和哈希。例如,"https://example.com/foo
" 匹配任何搜索和任何哈希。同样,"https://example.com
" 匹配该来源上的任何 URL。这类似于 处理 URLPatternInit 中有关更具体组件的概念(例如,搜索比路径名更具体),但构造器语法只有少数几种情况可以在不同时指定较不具体的组件的情况下指定更具体的组件。
用户名和密码组件始终为通配,除非明确指定。
如果指定了主机名而未指定端口,则假定端口为默认端口。如果作者想匹配任何端口,他们必须显式写为 :*
。例如,"https://*
" 是端口 443 上的任何 HTTPS 来源,而 "https://*:*
" 是任何端口上的任何 HTTPS 来源。
-
令 parser 为一个新的 构造函数字符串解析器,其 输入 为 input,并且 token 列表 是运行 tokenize 得到的,给定 input 和 "
lenient
"。 -
当 parser 的 token 索引 小于 parser 的 token 列表 的 大小时:
-
设置 parser 的 token 增量 为 1。
在解析循环的每次迭代中,parser 的 token 索引 将按其 token 增量 进行递增。通常情况下,递增量为 1,但在某些情况下会设置为 0。然后每次循环的顶部,token 增量 总是重置为 1。
-
如果 parser 的 token 列表[parser 的 token 索引] 的 类型 为 "
end
",则:-
如果我们在 "
init
" 状态下到达字符串末尾,那么我们未能找到协议终止符,这必须是一个相对的 URLPattern 构造函数字符串。-
运行 回退,给定 parser。
接下来我们确定相对模式从哪个组件开始。相对路径名最为常见,但 URL 和 URLPattern 构造函数字符串也可以从 search 或 hash 组件开始。
-
如果运行 是否为 hash 前缀,给定 parser 的结果为 true,则运行 更改状态,给定 parser,"
hash
" 和 1。 -
否则,如果运行 是否为 search 前缀,给定 parser 的结果为 true:
-
否则:
-
继续。
-
-
如果我们在 "
authority
" 状态下到达字符串末尾,那么我们未能找到 "@
"。因此没有用户名或密码。 -
中断。
-
-
如果运行 是否为组开启符,给定 parser 的结果为 true:
-
如果 parser 的 组深度 大于 0:
-
切换 parser 的 状态,并运行相关步骤:
- "
init
" - "
protocol
" -
-
如果运行 是否为协议后缀,给定 parser 的结果为 true:
-
运行 计算协议是否匹配特殊方案标志,给定 parser。
我们需要尽早编译协议组件,以确定它是否匹配任何 特殊方案。如果匹配,则某些特殊规则将适用。它决定了路径名是否默认值为 "
/
",以及我们是否会查找用户名、密码、主机名和端口组件。权限斜线也可能导致我们查找这些组件。否则,我们将其视为 "不透明路径 URL",直接进入路径名组件。 -
设置 next state 为 "
pathname
"。 -
设置 skip 为 1。
-
如果运行 下一个是权限斜线,给定 parser 的结果为 true:
-
设置 next state 为 "
authority
"。 -
设置 skip 为 3。
-
-
否则,如果 parser 的 协议匹配特殊方案标志 为 true,则将 next state 设置为 "
authority
"。 -
运行 更改状态,给定 parser、next state 和 skip。
-
-
- "
authority
" -
-
如果运行 是否为身份终止符,给定 parser 的结果为 true,则运行 回退并设置状态,给定 parser 和 "
username
"。 -
否则,如果以下任意一个为 true:
- 运行 是否为路径名开始符,给定 parser;
- 运行 是否为 search 前缀,给定 parser;或
- 运行 是否为 hash 前缀,给定 parser,
-
- "
username
" - "
password
" - "
hostname
" -
-
如果运行 是否为 IPv6 开启符,给定 parser 的结果为 true,则将 parser 的 主机名 IPv6 括号深度 增加 1。
-
否则,如果运行 是否为 IPv6 关闭符,给定 parser 的结果为 true,则将 parser 的 主机名 IPv6 括号深度 减少 1。
-
否则,如果运行 是否为端口前缀,给定 parser 的结果为 true,且 parser 的 主机名 IPv6 括号深度 为 0,则运行 更改状态,给定 parser,"
port
" 和 1。 -
否则,如果运行 是否为路径名开始符,给定 parser 的结果为 true,则运行 更改状态,给定 parser,"
pathname
" 和 0。 -
否则,如果运行 是否为 search 前缀,给定 parser 的结果为 true,则运行 更改状态,给定 parser,"
search
" 和 1。 -
否则,如果运行 是否为 hash 前缀,给定 parser 的结果为 true,则运行 更改状态,给定 parser,"
hash
" 和 1。
-
- "
port
" -
-
如果运行 是否为路径名开始符,给定 parser 的结果为 true,则运行 更改状态,给定 parser,"
pathname
" 和 0。 -
否则,如果运行 是否为 search 前缀,给定 parser 的结果为 true,则运行 更改状态,给定 parser,"
search
" 和 1。 -
否则,如果运行 是否为 hash 前缀,给定 parser 的结果为 true,则运行 更改状态,给定 parser,"
hash
" 和 1。
-
- "
pathname
" -
-
如果运行 是否为 search 前缀,给定 parser 的结果为 true,则运行 更改状态,给定 parser,"
search
" 和 1。 -
否则,如果运行 是否为 hash 前缀,给定 parser 的结果为 true,则运行 更改状态,给定 parser,"
hash
" 和 1。
-
- "
search
" -
-
如果运行 是否为 hash 前缀,给定 parser 的结果为 true,则运行 更改状态,给定 parser,"
hash
" 和 1。
-
- "
hash
" -
-
什么都不做。
-
- "
done
" -
-
断言:此步骤从未到达。
-
- "
-
-
如果 parser 的 结果 包含 "
主机名
" 且不包含 "端口
",则将 parser 的 结果["端口
"] 设置为空字符串。这是一个特殊情况,因为当作者未指定端口时,他们通常是指默认端口。如果任何端口都可以接受,作者可以显式将其指定为通配符。例如,"https://example.com/*
" 不匹配以 "https://example.com:8443/
" 开头的 URL,这是一个不同的来源。 -
返回 parser 的 结果。
-
如果 parser 的 状态 不是 "
init
",不是 "authority
",也不是 "done
",那么将 parser 的 结果[parser 的 状态] 设置为运行 生成组件字符串 给定 parser 的结果。 -
如果 parser 的 状态 不是 "
init
" 且 new state 不是 "done
",那么:-
如果 parser 的 状态 是 "
protocol
","authority
","username
" 或 "password
";new state 是 "port
","pathname
","search
" 或 "hash
";并且 parser 的 结果["hostname
"] 不 存在,那么将 parser 的 结果["hostname
"] 设置为空字符串。 -
如果 parser 的 状态 是 "
protocol
","authority
","username
","password
","hostname
" 或 "port
";new state 是 "search
" 或 "hash
";并且 parser 的 结果["pathname
"] 不 存在,那么:-
如果 parser 的 协议匹配特殊方案标志 为真,则将 parser 的 结果["
pathname
"] 设置为 "/
"。
-
-
如果 parser 的 状态 是 "
protocol
","authority
","username
","password
","hostname
","port
" 或 "pathname
";new state 是 "hash
";并且 parser 的 结果["search
"] 不 存在,那么将 parser 的 结果["search
"] 设置为空字符串。
-
-
将 parser 的 状态 设置为 new state。
-
将 parser 的 token 索引 增加 skip。
-
将 parser 的 token 增量 设置为 0。
-
让token成为运行获取安全令牌的结果,并传入parser和index。
-
如果token的值不是value,则返回false。
-
如果以下任一项为true:
- token的类型是"
char
"; - token的类型是"
escaped-char
"; - token的类型是"
invalid-char
",
则返回true。
- token的类型是"
-
返回false。
-
返回运行is a non-special pattern char的结果,传入parser、parser的token index和"
:
"。
-
如果运行is a non-special pattern char的结果为false,传入parser、parser的token index + 1 和"
/
",则返回false。 -
如果运行is a non-special pattern char的结果为false,传入parser、parser的token index + 2 和"
/
",则返回false。 -
返回true。
-
返回运行is a non-special pattern char的结果,传入parser、parser的token index和"
@
"。
-
返回运行is a non-special pattern char的结果,传入parser、parser的token index和"
:
"。
-
返回运行is a non-special pattern char的结果,传入parser、parser的token index和"
:
"。
-
返回运行is a non-special pattern char的结果,传入parser、parser的token index和"
/
"。
-
如果运行is a non-special pattern char的结果为true,传入parser、parser的token index和"
?
",则返回true。 -
如果parser的令牌列表[parser的token index]的值不是"
?
",则返回false。 -
让previous index等于parser的token index − 1。
-
如果previous index小于0,则返回true。
-
让previous token成为运行获取安全令牌的结果,并传入parser和previous index。
-
如果以下任一项为true,则返回false:
-
返回true。
-
返回运行is a non-special pattern char的结果,传入parser、parser的token index和"
#
"。
-
如果parser的令牌列表[parser的token index]的类型是"
open
",则返回true。 -
否则返回false。
-
如果parser的令牌列表[parser的token index]的类型是"
close
",则返回true。 -
否则返回false。
-
返回运行is a non-special pattern char的结果,传入parser、parser的token index和"
[
"。
-
返回运行is a non-special pattern char的结果,传入parser、parser的token index和"
]
"。
-
断言:parser的token index小于parser的令牌列表的大小。
-
设token为parser的令牌列表[parser的token index]。
-
设component start token为运行获取安全令牌的结果,并传入parser和parser的component start。
-
设component start input index为component start token的索引。
-
设end index为token的索引。
-
设protocol string为运行make a component string的结果,并传入parser。
-
设protocol component为运行编译组件的结果,并传入protocol string、规范化协议和默认选项。
-
如果运行协议组件与特殊方案匹配的结果为true,设置parser的protocol matches a special scheme flag为true。
2. 模式字符串
模式字符串 是用来匹配一组目标字符串的字符串。一个格式良好的模式字符串符合特定的模式语法。这种模式语法直接基于流行的path-to-regexp JavaScript 库的语法。
它可以被解析以生成一个部分列表,该列表按顺序描述了模式字符串要匹配时必须出现在组件字符串中的内容。
/
,在主机名中为.
)。例如,路径名模式"/blog/:title
"会匹配"/blog/hello-world
",但不匹配"/blog/2012/02
"。
也可以使用括号内的正则表达式代替,因此路径名模式"/blog/:year(\\d+)/:month(\\d+)
"会匹配"/blog/2012/02
"。
组也可以使用修饰符来设置为可选或重复。例如,路径名模式"/products/:id?
"会匹配"/products
"和"/products/2
"(但不匹配"/products/
")。特别是在路径名中,组会自动要求前导/
;为了避免这种情况,可以显式分隔组,如路径名模式"/products/{:id}?
"所示。
也可以使用通配符*
来尽可能多地匹配,如路径名模式"/products/*
"。
2.1. 解析模式字符串
2.1.1. 令牌
令牌是一个结构体,表示模式字符串中的一个词法令牌。
一个令牌具有相关的类型,这是一个字符串,初始值为"invalid-char
"。它必须是以下之一:
- "
open
" - 该令牌表示一个U+007B (
{
) 码点。 - "
close
" - 该令牌表示一个U+007D (
}
) 码点。 - "
regexp
" - 该令牌表示一个格式为"
(<regular expression>)
"的字符串。正则表达式必须仅由ASCII码点组成。 - "
name
" - 该令牌表示一个格式为"
:<name>
"的字符串。name值被限制为与JavaScript标识符一致的码点。 - "
char
" - 该令牌表示一个有效的模式码点,没有任何特殊的语法含义。
- "
escaped-char
" - 该令牌表示一个使用反斜杠转义的码点,如"
\<char>
"。 - "
other-modifier
" - 该令牌表示一个匹配组修饰符,它是U+003F (
?
) 或U+002B (+
)码点。 - "
asterisk
" - 该令牌表示一个U+002A (
*
)码点,可以是一个通配符匹配组或一个匹配组修饰符。 - "
end
" - 该令牌表示模式字符串的结束。
- "
invalid-char
" - 该令牌表示模式中无效的码点。这可能是由于码点值本身或其在模式中相对于其他语法元素的位置所致。
一个令牌具有相关的索引,这是一个数字,初始值为0。它是令牌表示的模式字符串中第一个码点的位置。
一个令牌具有相关的值,这是一个字符串,初始为空。它包含令牌表示的模式字符串中的码点。
2.1.2. 令牌化
令牌化策略 是一个字符串,必须为 "strict
" 或 "lenient
"。
令牌化器 是一个结构体。
令牌化器 具有相关的 输入,是一个模式字符串,初始值为空字符串。
令牌化器 具有相关的 策略,是一个令牌化策略,初始为"strict
"。
令牌化器 具有相关的 令牌列表,是一个令牌列表,初始为一个空的列表。
令牌化器 具有相关的 索引,是一个数字,初始为0。
令牌化器 具有相关的 下一个索引,是一个数字,初始为0。
令牌化器 具有相关的 码点,是一个 Unicode 码点,初始为 null。
-
让tokenizer成为一个新的令牌化器。
-
将tokenizer的输入设置为input。
-
将tokenizer的策略设置为policy。
-
当tokenizer的索引小于tokenizer的输入的码点长度时:
-
运行查找并获取下一个码点,给定tokenizer和tokenizer的索引。
-
如果tokenizer的码点是 U+002A (
*
):-
运行添加一个带有默认位置和长度的令牌,给定tokenizer和"
asterisk
"。 -
继续。
-
-
如果tokenizer的码点是 U+002B (
+
) 或 U+003F (?
):-
运行添加一个带有默认位置和长度的令牌,给定tokenizer和"
other-modifier
"。 -
继续。
-
-
如果tokenizer的码点是 U+005C (
\
): -
如果tokenizer的码点是 U+007B (
{
):-
运行添加一个带有默认位置和长度的令牌,给定tokenizer和"
open
"。 -
继续。
-
-
如果tokenizer的码点是 U+007D (
}
):-
运行添加一个带有默认位置和长度的令牌,给定tokenizer和"
close
"。 -
继续。
-
-
如果tokenizer的码点是 U+003A (
:
):-
让name position成为tokenizer的下一个索引。
-
让name start成为name position。
-
当name position小于tokenizer的输入的码点长度时:
-
运行查找并获取下一个码点,给定tokenizer和name position。
-
如果name position等于name start,则first code point为true,否则为false。
-
运行检查是否为有效名称码点,给定tokenizer的码点和first code point。
-
如果valid code point为false,则跳出。
-
将name position设置为tokenizer的下一个索引。
-
-
如果name position小于或等于name start:
-
运行添加一个带有默认长度的令牌,给定tokenizer,"
name
",name position和name start。 -
继续。
-
-
如果tokenizer的码点是 U+0028 (
(
):-
设depth为 1。
-
设regexp position为tokenizer的下一个索引。
-
设regexp start为regexp position。
-
设error为 false。
-
当regexp position小于tokenizer的输入的码点长度时:
-
运行查找并获取下一个码点,给定tokenizer和regexp position。
-
如果运行检查是否为 ASCII的结果表明tokenizer的码点为 false:
-
如果regexp position等于regexp start,并且tokenizer的码点是 U+003F (
?
): -
如果tokenizer的码点是 U+005C (
\
): -
如果tokenizer的码点是 U+0029 (
)
): -
否则如果tokenizer的码点是 U+0028 (
(
): -
将regexp position设为tokenizer的下一个索引。
-
-
如果error为 true,继续。
-
如果depth不为零:
-
设regexp length为regexp position减去regexp start再减 1。
-
如果regexp length为零:
-
运行添加一个令牌,给定tokenizer,"
regexp
",regexp position,regexp start,以及regexp length。 -
继续。
-
-
运行添加一个带有默认位置和长度的令牌,给定tokenizer和"
char
"。
-
-
运行添加一个默认长度的令牌,给定tokenizer,"
end
",tokenizer的索引,以及tokenizer的索引。 -
返回tokenizer的令牌列表。
-
设computed length为next position减去value position。
-
运行添加令牌,给定tokenizer,type,next position,value position,以及computed length。
-
运行添加一个默认长度的令牌,给定tokenizer,type,tokenizer的下一个索引,以及tokenizer的索引。
-
运行添加一个默认长度的令牌,给定tokenizer,"
invalid-char
",next position,以及value position。
-
如果first为 true,返回检查码点是否包含在IdentifierStart码点集中的结果。
-
否则,返回检查码点是否包含在IdentifierPart码点集中的结果。
-
如果码点在 U+0000 到 U+007F 之间(含),则返回 true。
-
否则返回 false。
2.1.3. 部分
部分是一个表示解析器模式字符串的一部分的结构。它最多可以包含一个匹配组,一个固定的文本前缀,一个固定的文本后缀,以及一个修饰符。它可以仅包含一个固定的文本字符串或一个匹配组。
一个部分具有一个关联的类型,该类型是一个字符串,必须在创建时设置。它必须是以下之一:
- "
fixed-text
" - 该部分表示一个简单的固定文本字符串。
- "
regexp
" - 该部分表示具有自定义正则表达式的匹配组。
- "
segment-wildcard
" - 该部分表示匹配组,匹配直到下一个分隔符码点的所有码点。通常用于像"
:foo
"这样的命名组,它没有自定义正则表达式。 - "
full-wildcard
" - 该部分表示一个贪婪地匹配所有码点的匹配组。通常用于"
*
"通配符匹配组。
一个部分具有一个关联的值,一个字符串,必须在创建时设置。
一个部分具有一个关联的修饰符,一个字符串,必须在创建时设置。它必须是以下之一:
- "
none
" - 该部分没有修饰符。
- "
optional
" - 该部分具有一个可选的修饰符,由 U+003F (
?
) 码点指示。 - "
zero-or-more
" - 该部分具有"零或更多"修饰符,由 U+002A (
*
) 码点指示。 - "
one-or-more
" - 该部分具有"一个或更多"修饰符,由 U+002B (
+
) 码点指示。
一个部分具有一个关联的名称,一个字符串,初始为空字符串。
一个部分具有一个关联的前缀,一个字符串,初始为空字符串。
一个部分具有一个关联的后缀,一个字符串,初始为空字符串。
2.1.4. 选项
选项是一个结构,其中包含控制模式字符串行为的不同设置。这些选项最初来自path-to-regexp。我们只包括在 URLPattern 规范中修改的选项,排除其他选项。为了便于比较,本规范的行为类似于path-to-regexp,其中strict
、start
和end
始终设置为false。
选项具有一个关联的分隔符码点,一个字符串,必须在创建时设置。它必须包含一个ASCII 码点或空字符串。此码点被视为段分隔符,并用于确定:foo
命名组应匹配的范围。例如,如果分隔符码点是"/
",那么"/:foo
"将匹配"/bar
",但不会匹配"/bar/baz
"。如果分隔符码点为空字符串,则示例模式将匹配两个字符串。
选项具有一个关联的前缀码点,一个字符串,必须在创建时设置。它必须包含一个ASCII 码点或空字符串。如果在匹配组前立即发现,该码点被视为自动前缀。这在匹配组被修改为可选或重复时尤为重要。例如,如果前缀码点是"/
",那么"/foo/:bar?/baz
"会将"/
"视为一个前缀,该前缀与命名组一起变得可选。因此,在此示例中,模式将匹配"/foo/baz
"。
选项具有一个关联的忽略大小写,一个布尔值,必须在创建时设置。默认值为false。根据设置的值(true或false),此标志分别启用区分大小写或不区分大小写的匹配。为了比较,可以将此大小写视为path-to-regexp中的sensitive
选项的反义词。
2.1.5. 解析
模式解析器是一个结构。
模式解析器具有一个关联的令牌列表,一个令牌列表,初始为空的列表。
模式解析器具有一个关联的编码回调,一个编码回调,必须在创建时设置。
模式解析器具有一个关联的段通配符正则表达式,一个字符串,必须在创建时设置。
模式解析器具有一个关联的部分列表,一个部分列表,初始为空的列表。
模式解析器具有一个关联的待处理固定值,一个字符串,初始为空字符串。
模式解析器具有一个关联的索引,一个数字,初始为 0。
模式解析器具有一个关联的下一个数字名称,一个数字,初始为 0。
-
设parser为一个新的模式解析器,其编码回调为encoding callback,且段通配符正则表达式是运行生成段通配符正则表达式给定的options的结果。
-
-
设regexp or wildcard token为运行尝试消费正则或通配符令牌,给定parser和name token的结果。
-
如果name token不为null或regexp or wildcard token不为null:
如果有一个匹配组,我们需要立即添加部分。
-
设fixed token为char token。
如果没有匹配组,那么我们需要缓冲任何固定文本。在将其作为"
fixed-text
"部分添加之前,我们希望收集尽可能多的文本。 -
如果fixed token为null,则将fixed token设置为运行尝试消费令牌给定的parser和"
escaped-char
"的结果。 -
如果fixed token不为null:
-
如果open token不为null:
-
运行从待处理固定值中可能添加部分,给定parser。
-
返回parser的部分列表。
完整通配符正则表达式值是字符串".*
"。
-
将result设为"
[^
"。 -
将运行转义正则表达式字符串给定的options的分隔符码点的结果追加到result的末尾。
-
将"
]+?
"追加到result的末尾。 -
返回result。
2.2. 将部分列表转换为正则表达式
-
令结果为"
^
"。 -
令名称列表为一个新的列表。
-
对每个部分的部分列表:
-
-
如果部分的修饰符是"
无
",则将运行转义正则表达式字符串后的结果附加到结果的末尾。 -
否则:
带有修饰符的"
固定文本
"部分使用非捕获组。其形式如下。(?:<固定文本>)<修饰符>
-
将"
(?:
"附加到结果的末尾。 -
将运行转义正则表达式字符串后的结果附加到结果的末尾。
-
将"
)
"附加到结果的末尾。 -
将运行将修饰符转换为字符串后的结果附加到结果的末尾。
-
-
继续。
-
-
我们在并行列表中收集匹配组名称。这主要是为了与path-to-regexp保持一致。尽管可以尝试转换为使用正则表达式命名捕获组,但考虑到算法的复杂性,存在引入意外错误的风险。此外,如果我们最终向网页暴露生成的正则表达式,我们希望与path-to-regexp保持兼容,它表明不太可能切换到使用命名捕获组。
-
令正则表达式值为部分的值。
-
如果部分的类型是"
段通配符
",则将正则表达式值设置为运行生成段通配符正则表达式后的结果。 -
否则,如果部分的类型是"
全通配符
",则将正则表达式值设置为全通配符正则表达式值。 -
如果没有前缀或后缀,则生成依赖于修饰符。如果没有修饰符或只有可选修饰符,它将使用以下简单形式:
(<正则表达式值>)<修饰符>
然而,如果存在重复修饰符,我们将使用更复杂的形式:
((?:<正则表达式值>)<修饰符>)
-
-
将"
(
"附加到结果的末尾。 -
将正则表达式值附加到结果的末尾。
-
将"
)
"附加到结果的末尾。 -
将运行将修饰符转换为字符串后的结果附加到结果的末尾。
-
-
否则:
-
将"
((?:
"附加到结果的末尾。 -
将正则表达式值附加到结果的末尾。
-
将"
)
"附加到结果的末尾。 -
将运行将修饰符转换为字符串后的结果附加到结果的末尾。
-
将"
)
"附加到结果的末尾。
-
-
继续。
-
-
本节处理带有前缀或后缀的非重复部分。内部捕获组包含主要的正则表达式值。然后,内部组与前缀或后缀结合在一个外部非捕获组中。最后,应用修饰符。结果形式如下。
(?:<前缀>(<正则表达式值>)<后缀>)<修饰符>
-
将"
(?:
"附加到结果的末尾。 -
将运行转义正则表达式字符串后的结果附加到结果的末尾。
-
将"
(
"附加到结果的末尾。 -
将正则表达式值附加到结果的末尾。
-
将"
)
"附加到结果的末尾。 -
将运行转义正则表达式字符串后的结果附加到结果的末尾。
-
将"
)
"附加到结果的末尾。 -
将运行将修饰符转换为字符串后的结果附加到结果的末尾。
-
继续。
-
-
将"
(?:
"附加到结果的末尾。 -
将运行转义正则表达式字符串后的结果附加到结果的末尾。
-
将"
((?:
"附加到结果的末尾。 -
将正则表达式值附加到结果的末尾。
-
将"
)(?:
"附加到结果的末尾。 -
将运行转义正则表达式字符串后的结果附加到结果的末尾。
-
将运行转义正则表达式字符串后的结果附加到结果的末尾。
-
将"
(?:
"附加到结果的末尾。 -
将正则表达式值附加到结果的末尾。
-
将"
))*)
"附加到结果的末尾。 -
将运行转义正则表达式字符串后的结果附加到结果的末尾。
-
将"
)
"附加到结果的末尾。
-
-
将"
$
"附加到结果的末尾。 -
返回 (结果, 名称列表)。
2.3. 将部分列表转换为模式字符串
-
令result为空字符串。
-
令index list为获取部分列表的索引后的结果。
-
对每个index的index list:
-
令part为part list[index]。
-
如果index大于0,则令previous part为part list[index - 1],否则令其为null。
-
如果index小于index list的大小 - 1,则令next part为part list[index + 1],否则令其为null。
-
如果part的类型是"
fixed-text
": -
令needs grouping为true,如果以下条件中至少有一个为真,否则为false:
-
如果以下所有条件为真:
则: -
如果以下所有条件为真:
则设置needs grouping为true。 -
如果needs grouping为true,则将"
{
"附加到result的末尾。 -
如果custom name为true:
-
将"
:
"附加到result的末尾。 -
将part的name附加到result的末尾。
-
-
-
将"
(
"附加到result的末尾。 -
将part的value附加到result的末尾。
-
将"
)
"附加到result的末尾。
-
-
否则,如果part的类型是"
segment-wildcard
",且custom name为false:-
将"
(
"附加到result的末尾。 -
将运行生成段通配符正则表达式给定options附加到result的末尾。
-
将"
)
"附加到result的末尾。
-
-
否则,如果part的类型是"
full-wildcard
":-
如果custom name为false,并且以下条件之一为真:
- previous part为null;或
- previous part的类型是"
fixed-text
";或 - previous part的修饰符不是"
none
";或 - needs grouping为true;或
- part的前缀不是空字符串
*
"附加到result的末尾。 -
否则:
-
将"
(
"附加到result的末尾。 -
将全通配符正则表达式值附加到result的末尾。
-
将"
)
"附加到result的末尾。
-
-
-
如果以下所有条件为真:
则将U+005C (\
)附加到result的末尾。 -
如果needs grouping为true,则将"
}
"附加到result的末尾。 -
将运行将修饰符转换为字符串给定part的修饰符附加到result的末尾。
-
-
返回result。
-
如果modifier是"
zero-or-more
",则返回"*
"。 -
如果modifier是"
optional
",则返回"?
"。 -
如果modifier是"
one-or-more
",则返回"+
"。 -
返回空字符串。
3. 规范化
3.1. 编码回调
-
令result为空字符串。
-
-
如果以下所有条件为真:
- 码点不是ASCII十六进制数字;
- 码点不是U+005B (
[
); - 码点不是U+005D (
]
);且 - 码点不是U+003A (
:
),
则抛出
TypeError
。 -
将运行ASCII小写给定码点的结果附加到result的末尾。
-
-
返回result。
-
如果value为空字符串,则返回value。
-
如果value的第一个码点是U+002F(
/
),则leading slash为true,否则为false。 -
如果leading slash为false,则modified value为"
/-
",否则为空字符串。URL解析器将自动在规范化的路径名前加上前导斜杠。这在这里不起作用,因为该算法在用作编码回调时会处理路径的部分,而不是整个路径。因此,我们通过插入自己的前导斜杠来禁用斜杠的添加。还在此处插入了一个额外的字符,以避免由于虚假的前导斜杠被解释为"
/.
"序列而无意中压缩前导点。然后在下面从结果中删除这些插入的字符。注意,实施者可以选择在其URL解析代码中简单地禁用斜杠添加,而不是通过此算法插入和删除字符来支付性能成本。
-
将value附加到modified value的末尾。
-
令dummyURL为一个新的URL记录。
-
令parseResult为运行基本URL解析器的结果,传入modified value,并使用dummyURL作为URL,并使用路径开始状态作为状态覆盖。
-
如果parseResult为失败,则抛出
TypeError
。 -
令result为dummyURL的URL路径序列化结果。
-
如果leading slash为false,则将result设置为从2到字符串末尾的码点子字符串。
-
返回result。
3.2. URLPatternInit
处理
URLPatternInit
处理,传入init、字符串type、字符串或null的protocol、username、password、hostname、port、pathname、search、hash:
-
令result为创建一个新的
URLPatternInit
的结果。 -
令baseURL为null。
-
base URL可用于提供额外的上下文,但对于每个组件,如果init包含的组件至少与base URL中的组件一样具体,则不会继承任何内容。
如果组件在以下两个列表中较晚出现(与它们在URL语法中出现的顺序非常相似),则该组件更具体:
-
协议、主机名、端口、路径名、查询、哈希
-
协议、主机名、端口、用户名、密码
构建
URLPattern
时,用户名和密码也从不从base URL继承。(不过,在解析作为test()
或exec()
的参数传入的URL时,用户名和密码是从base URL继承的。)-
如果baseURL为失败,则抛出
TypeError
。 -
如果init["
protocol
"]不存在,则将result["protocol
"]设置为处理base URL字符串的结果,传入baseURL的scheme和type。 -
如果type不是"
pattern
",并且init不包含"protocol
"、"hostname
"、"port
"和"username
",则将result["username
"]设置为处理base URL字符串的结果,传入baseURL的username和type。 -
如果type不是"
pattern
",并且init不包含"protocol
"、"hostname
"、"port
"、"username
"和"password
",则将result["password
"]设置为处理base URL字符串的结果,传入baseURL的password和type。 -
如果init不包含"
protocol
"或"hostname
",则:-
令baseHost为baseURL的主机。
-
如果baseHost为null,则将baseHost设置为空字符串。
-
将result["
hostname
"]设置为处理base URL字符串的结果,传入baseHost和type。
-
-
如果init不包含"
protocol
"、"hostname
"、"port
"、"pathname
",则将result["pathname
"]设置为处理base URL字符串的结果,传入URL路径序列化baseURL和type。 -
如果init不包含"
protocol
"、"hostname
"、"port
"、"pathname
"和"search
",则:-
令baseQuery为baseURL的查询。
-
如果baseQuery为null,则将baseQuery设置为空字符串。
-
将result["
search
"]设置为处理base URL字符串的结果,传入baseQuery和type。
-
-
如果init不包含"
protocol
"、"hostname
"、"port
"、"pathname
"、"search
"和"hash
",则:-
令baseFragment为baseURL的片段。
-
如果baseFragment为null,则将baseFragment设置为空字符串。
-
将result["
hash
"]设置为处理base URL字符串的结果,传入baseFragment和type。
-
-
-
如果init["
protocol
"]存在,则将result["protocol
"]设置为处理init协议的结果,传入init["protocol
"]和type。 -
如果init["
username
"]存在,则将result["username
"]设置为处理init用户名的结果,传入init["username
"]和type。 -
如果init["
password
"]存在,则将result["password
"]设置为处理init密码的结果,传入init["password
"]和type。 -
如果init["
hostname
"]存在,则将result["hostname
"]设置为处理init主机名的结果,传入init["hostname
"]和type。 -
如果init["
port
"]存在,则将result["port
"]设置为处理init端口的结果,传入init["port
"]、result["protocol
"]和type。 -
如果init["
search
"]存在,则将result["search
"]设置为处理init查询的结果,传入init["search
"]和type。 -
如果init["
hash
"]存在,则将result["hash
"]设置为处理init哈希的结果,传入init["hash
"]和type。 -
返回result。
-
如果input为空字符串,则返回false。
-
如果input[0]是U+002F(
/
),则返回true。 -
如果type是"
url
",则返回false。 -
如果input的代码点长度小于2,则返回false。
-
如果input[0]是U+005C(
\
),并且input[1]是U+002F(/
),则返回true。 -
如果input[0]是U+007B(
{
),并且input[1]是U+002F(/
),则返回true。 -
返回false。
-
令strippedValue为给定的value,去掉一个结尾的U+003A(
:
),如果有的话。 -
如果type是"
pattern
",则返回strippedValue。 -
返回运行规范化协议的结果,传入strippedValue。
-
如果type是"
pattern
",则返回value。 -
返回运行规范化用户名的结果,传入value。
-
如果type是"
pattern
",则返回value。 -
返回运行规范化密码的结果,传入value。
-
如果type是"
pattern
",则返回value。 -
返回运行规范化主机名的结果,传入value。
-
如果type是"
pattern
",则返回portValue。 -
返回运行规范化端口的结果,传入portValue和protocolValue。
-
令strippedValue为给定的value,去掉一个开头的U+003F(
?
),如果有的话。 -
如果type是"
pattern
",则返回strippedValue。 -
返回运行规范化搜索的结果,传入strippedValue。
-
令strippedValue为给定的value,去掉一个开头的U+0023(
#
),如果有的话。 -
如果type是"
pattern
",则返回strippedValue。 -
返回运行规范化哈希的结果,传入strippedValue。
4. 在其他规范中使用URL模式
为了促进Web平台的一致性,集成此规范的其他文档应遵循以下指南,除非有充分的理由偏离。
-
接受简写。大多数作者的模式将是简单而直接的。因此,API应该接受这些常见情况的简写,并避免让作者采取额外步骤将其转换为完整的
URLPattern
对象。 -
尊重基础URL。就像URL通常相对于其环境的基础URL(最常见的是文档基础URL)进行解析一样,URL模式也应遵循这一点。
URLPattern
构造函数本身是一个例外,因为它直接暴露了该概念,类似于URL构造函数也不遵循基础URL,尽管平台的其余部分遵循。 -
明确正则表达式组。某些API可能仅允许不具有正则表达式组的URL模式,例如,因为用户代理可能在不同的线程或进程中实现它们,而不是执行作者脚本的地方,并且由于安全或性能问题,JavaScript引擎通常不会在那运行。如果是这样,应该清楚地记录这一点(参考是否具有正则表达式组),并且该操作应尽早报告错误(例如,抛出JavaScript异常)。如果可能,应使其具有特征检测功能,以便将来可以解除此限制。避免在未咨询本规范编辑者的情况下创建不同的URL模式子集。
-
明确匹配的URL。例如,抓取期间的算法可能操作没有片段的URL。如果是这样,规范应明确说明,并可以建议如果使用了无法匹配的模式(例如,因为它需要非空的片段),则显示开发人员警告。
4.1. 与JavaScript API的集成
typedef (USVString 或 URLPatternInit 或 URLPattern );
URLPatternCompatible
JavaScript API应接受以下所有内容:
-
一个
URLPattern
对象 -
一个字典类对象,指定构造模式所需的组件
-
一个字符串(按照构造函数的字符串语法)
为了实现这一点,规范应接受URLPatternCompatible
作为操作或字典成员的参数,并使用以下算法处理它,使用适当的环境设置对象的API基础URL或等效的。
URLPattern
对象 URLPatternCompatible
input,给定URL baseURL和realm realm,执行以下步骤:
-
如果input的特定类型是
URLPattern
:-
返回input。
-
-
否则:
-
令pattern为新的
URLPattern
,带有realm。 -
将pattern的关联URL模式设置为运行从Web IDL值构建URL模式的结果,传入input和baseURL。
-
返回pattern。
-
这允许作者简洁地指定大多数模式,并在必要时使用构造函数来访问不常见的选项。基础URL的隐式使用与HTML的解析URL算法类似且一致。[HTML]
4.2. 与JSON数据格式的集成
包含URL模式的JSON数据格式应当与JavaScript API的行为保持一致,并接受以下两种格式:
-
一个指定构造模式所需组件的对象
-
一个字符串(遵循构造函数的字符串语法)
如果某个规范有一个Infra值(例如,在使用将JSON字符串解析为Infra值之后),请使用以下算法,并使用适当的基础URL(默认情况下为JSON资源的URL)。[INFRA]
-
令serializedBaseURL为baseURL的序列化。
-
如果rawPattern是字符串,则:
-
否则,如果rawPattern是映射,则:
-
令init为«[ "
baseURL
" → serializedBaseURL ]»,表示一个类型为URLPatternInit
的字典。 -
对于每个 key → value的rawPattern:
-
如果key不是
URLPatternInit
或其继承字典的标识符,value不是字符串,或者该成员的类型未声明为USVString
,则返回null。如果URLPatternInit
增加了其他类型的成员,这将需要更新。如果对其他规范有用,将来的规范版本可能还会有一种不那么严格的模式。 -
将init[key]设置为value。
-
-
返回运行创建URL模式的结果,传入init、null和一个空的映射。
将来可能需要在此传递非空选项。
-
-
否则,返回null。
规范可能希望在其格式中预留空间,以接受URLPatternOptions
的选项、覆盖基础URL或类似内容,因为在这种情况下不可能像在JavaScript API中那样直接构造URLPattern
对象。例如,Speculation Rules接受一个"relative_to
"键,可以用来切换到使用文档基础URL,而不是JSON资源的URL。[SPECULATION-RULES]
致谢
编辑们要感谢 Alex Russell, Anne van Kesteren, Asa Kusuma, Blake Embrey, Cyrus Kasaaian, Daniel Murphy, Darwin Huang, Devlin Cronin, Domenic Denicola, Dominick Ng, Jake Archibald, Jeffrey Posnick, Jeremy Roman, Jimmy Shen, Joe Gregorio, Joshua Bell, Kenichi Ishibashi, Kenji Baheux, Kenneth Rohde Christiansen, Kingsley Ngan, Kinuko Yasuda, L. David Baron, Luca Casonato, Łukasz Anforowicz, Makoto Shimazu, Marijn Kruisselbrink, Matt Falkenhagen, Matt Giuca, Michael Landry, R. Samuel Klatchko, Rajesh Jagannathan, Ralph Chelala, Sangwhan Moon, Sayan Pal, Victor Costan, Yoshisato Yanagisawa, 以及 Youenn Fablet 对本规范的贡献。
特别感谢Blake Embrey和其他pillarjs/path-to-regexp 贡献者,他们构建了一个出色的开源库,受到了广泛欢迎。
同样特别感谢Kenneth Rohde Christiansen为polyfill所做的工作。他为适应不断变化的URLPattern
API做了大量工作。
该标准由 Ben Kelly (Google, wanderview@chromium.org), Jeremy Roman (Google, jbroman@chromium.org),以及 宍戸俊哉 (Shunya Shishido, Google, sisidovski@chromium.org)撰写。
知识产权
版权所有 © WHATWG (Apple, Google, Mozilla, Microsoft)。本作品采用知识共享署名 4.0 国际许可协议授权。若有部分内容被纳入源代码,则该部分源代码根据BSD 3-Clause License授权。
这是现行标准。若有兴趣查看专利审查版本,请参阅现行标准审查草案。