core: registrableDomain treats generic second-level labels under ccTLDs (gov.py, go.cr, gouv.ht, ac.ir, co.zw…) as public suffixes — institutions there are distinct organizations
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 changed file +5 −0
modified
packages/core/src/coverage-schema.ts
+5 −0
@@ -133,6 +133,9 @@ const MULTI_SUFFIX = new Set([ | ||
| 133 | 133 | "org.au", "com.au", "co.ke", |
| 134 | 134 | ]); |
| 135 | 135 | |
| 136 | +/** Generic second-level labels under country-code TLDs (`gov.py`, `go.cr`, `gouv.ht`, `ac.ir`, `co.zw`…): institutions there are distinct organizations. */ | |
| 137 | +const CC_SECOND_LEVEL = new Set(["gov", "gouv", "gob", "go", "gv", "govt", "gub", "edu", "ac", "co", "com", "org", "net", "or", "ne", "mil", "sch", "nic", "res", "ltd", "plc", "me", "id", "asn", "lg", "ed", "ad", "re", "muni", "jus", "leg", "int", "info", "biz", "web", "pro", "nom", "ind", "firm", "gen", "per", "mod", "nhs", "police", "parliament", "judiciary", "govmu"]); | |
| 138 | + | |
| 136 | 139 | export function registrableDomain(host: string): string { |
| 137 | 140 | const h = host.toLowerCase().replace(/\.$/, "").replace(/^www\./, ""); |
| 138 | 141 | const parts = h.split("."); |
@@ -141,6 +144,8 @@ export function registrableDomain(host: string): string { | ||
| 141 | 144 | const last3 = parts.slice(-3).join("."); |
| 142 | 145 | if (MULTI_SUFFIX.has(last3) && parts.length >= 4) return parts.slice(-4).join("."); |
| 143 | 146 | if (MULTI_SUFFIX.has(last2)) return last3; |
| 147 | + const tld = parts[parts.length - 1]!; | |
| 148 | + if (tld.length === 2 && CC_SECOND_LEVEL.has(parts[parts.length - 2]!)) return last3; | |
| 144 | 149 | return last2; |
| 145 | 150 | } |
| 146 | 151 | |
| 147 | 152 | |