-
Notifications
You must be signed in to change notification settings - Fork 26.1k
/
match-remote-pattern.ts
68 lines (65 loc) · 2.06 KB
/
match-remote-pattern.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import type { RemotePattern } from './image-config'
export function matchRemotePattern(pattern: RemotePattern, url: URL): boolean {
if (pattern.protocol !== undefined) {
const actualProto = url.protocol.slice(0, -1)
if (pattern.protocol !== actualProto) {
return false
}
}
if (pattern.port !== undefined) {
if (pattern.port !== url.port) {
return false
}
}
if (pattern.pathname !== undefined) {
const patternParts = pattern.pathname.split('/')
const actualParts = url.pathname.split('/')
const len = Math.max(patternParts.length, actualParts.length)
for (let i = 0; i < len; i++) {
if (patternParts[i] === '**' && actualParts[i] !== undefined) {
// Double asterisk means "match everything until the end of the path"
// so we can break the loop early
break
}
if (patternParts[i] === '*') {
// Single asterisk means "match this part" so we can
// continue to the next part of the loop
continue
}
if (patternParts[i] !== actualParts[i]) {
return false
}
}
}
if (pattern.hostname !== undefined) {
const patternParts = pattern.hostname.split('.').reverse()
const actualParts = url.hostname.split('.').reverse()
const len = Math.max(patternParts.length, actualParts.length)
for (let i = 0; i < len; i++) {
if (patternParts[i] === '**' && actualParts[i] !== undefined) {
// Double asterisk means "match every subdomain"
// so we can break the loop early
break
}
if (patternParts[i] === '*') {
// Single asterisk means "match this subdomain" so we can
// continue to the next part of the loop
continue
}
if (patternParts[i] !== actualParts[i]) {
return false
}
}
}
return true
}
export function hasMatch(
domains: string[],
remotePatterns: RemotePattern[],
url: URL
): boolean {
const allPatterns = remotePatterns.concat(
domains.map((hostname) => ({ hostname }))
)
return allPatterns.some((p) => matchRemotePattern(p, url))
}