@fgv/ts-bcp47 5.0.0-2 → 5.0.0-21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. package/.vscode/settings.json +58 -0
  2. package/config/api-extractor.json +343 -0
  3. package/config/rig.json +16 -0
  4. package/dist/tsdoc-metadata.json +1 -1
  5. package/lib/packlets/iana/jar/language-subtags/tags/converters.js +1 -0
  6. package/lib/test/data/iana/language-subtag-registry.json +57435 -0
  7. package/lib/test/data/iana/language-tag-extension-registry.json +38 -0
  8. package/lib/test/unit/bcp47/bcp47Tags/validate.test.d.ts +2 -0
  9. package/lib/test/unit/bcp47/canonicalTag.test.d.ts +2 -0
  10. package/lib/test/unit/bcp47/common.test.d.ts +2 -0
  11. package/lib/test/unit/bcp47/commonTestCases.d.ts +5 -0
  12. package/lib/test/unit/bcp47/commonTestCases.js +478 -0
  13. package/lib/test/unit/bcp47/helpers.test.d.ts +2 -0
  14. package/lib/test/unit/bcp47/languageRegistryData.test.d.ts +2 -0
  15. package/lib/test/unit/bcp47/languageTag.test.d.ts +2 -0
  16. package/lib/test/unit/bcp47/languageTagHelpers.d.ts +70 -0
  17. package/lib/test/unit/bcp47/languageTagHelpers.js +184 -0
  18. package/lib/test/unit/bcp47/match/chooser.test.d.ts +2 -0
  19. package/lib/test/unit/bcp47/match/similarity.test.d.ts +2 -0
  20. package/lib/test/unit/bcp47/normalizeTag.test.d.ts +2 -0
  21. package/lib/test/unit/bcp47/overrides.test.d.ts +2 -0
  22. package/lib/test/unit/bcp47/validTag.test.d.ts +2 -0
  23. package/lib/test/unit/bcp47/validateTag.test.d.ts +2 -0
  24. package/lib/test/unit/bcp47/wellFormedTag.test.d.ts +2 -0
  25. package/lib/test/unit/examples.test.d.ts +2 -0
  26. package/lib/test/unit/iana/common/datedRegistry.test.d.ts +2 -0
  27. package/lib/test/unit/iana/common/validate.test.d.ts +2 -0
  28. package/lib/test/unit/iana/jar/jarConverters.test.d.ts +2 -0
  29. package/lib/test/unit/iana/jar/language-subtags/tags/converters.test.d.ts +2 -0
  30. package/lib/test/unit/iana/jar/language-subtags/tags/validate.test.d.ts +2 -0
  31. package/lib/test/unit/iana/language-subtags/data.test.d.ts +2 -0
  32. package/lib/test/unit/iana/language-subtags/jarConverters.test.d.ts +2 -0
  33. package/lib/test/unit/iana/language-subtags/registry.test.d.ts +2 -0
  34. package/lib/test/unit/iana/language-subtags/scope.test.d.ts +2 -0
  35. package/lib/test/unit/iana/language-tag-extensions/extensionsRegistry.test.d.ts +2 -0
  36. package/lib/test/unit/iana/language-tag-extensions/validate.test.d.ts +2 -0
  37. package/lib/test/unit/unsd/csv.test.d.ts +2 -0
  38. package/lib/test/unit/unsd/regionCodes.test.d.ts +2 -0
  39. package/package.json +20 -20
  40. package/src/data/bcp/overrides.json +20 -0
  41. package/src/data/iana/language-subtags.json +57439 -0
  42. package/src/data/iana/language-tag-extensions.json +38 -0
  43. package/src/data/unsd/m49.json +3723 -0
  44. package/src/index.ts +29 -0
  45. package/src/packlets/bcp47/bcp47Subtags/converters.ts +33 -0
  46. package/src/packlets/bcp47/bcp47Subtags/index.ts +27 -0
  47. package/src/packlets/bcp47/bcp47Subtags/model.ts +46 -0
  48. package/src/packlets/bcp47/bcp47Subtags/validate.ts +55 -0
  49. package/src/packlets/bcp47/common.ts +85 -0
  50. package/src/packlets/bcp47/helpers.ts +117 -0
  51. package/src/packlets/bcp47/index.ts +38 -0
  52. package/src/packlets/bcp47/languageRegistryData.ts +304 -0
  53. package/src/packlets/bcp47/languageTag.ts +467 -0
  54. package/src/packlets/bcp47/languageTagParser.ts +307 -0
  55. package/src/packlets/bcp47/match/chooser.ts +164 -0
  56. package/src/packlets/bcp47/match/common.ts +57 -0
  57. package/src/packlets/bcp47/match/index.ts +26 -0
  58. package/src/packlets/bcp47/match/similarity.ts +243 -0
  59. package/src/packlets/bcp47/normalization/baseNormalizer.ts +146 -0
  60. package/src/packlets/bcp47/normalization/canonicalNormalizer.ts +102 -0
  61. package/src/packlets/bcp47/normalization/common.ts +84 -0
  62. package/src/packlets/bcp47/normalization/index.ts +27 -0
  63. package/src/packlets/bcp47/normalization/normalizeTag.ts +116 -0
  64. package/src/packlets/bcp47/normalization/preferredTagNormalizer.ts +213 -0
  65. package/src/packlets/bcp47/overrides/converters.ts +58 -0
  66. package/src/packlets/bcp47/overrides/defaultRegistries.ts +40 -0
  67. package/src/packlets/bcp47/overrides/index.ts +25 -0
  68. package/src/packlets/bcp47/overrides/model.ts +33 -0
  69. package/src/packlets/bcp47/overrides/overridesRegistry.ts +104 -0
  70. package/src/packlets/bcp47/validation/baseValidator.ts +132 -0
  71. package/src/packlets/bcp47/validation/common.ts +86 -0
  72. package/src/packlets/bcp47/validation/index.ts +29 -0
  73. package/src/packlets/bcp47/validation/isCanonical.ts +103 -0
  74. package/src/packlets/bcp47/validation/isInPreferredForm.ts +53 -0
  75. package/src/packlets/bcp47/validation/isStrictlyValid.ts +117 -0
  76. package/src/packlets/bcp47/validation/isValid.ts +122 -0
  77. package/src/packlets/bcp47/validation/isWellFormed.ts +102 -0
  78. package/src/packlets/bcp47/validation/validateTag.ts +175 -0
  79. package/src/packlets/iana/common/converters.ts +67 -0
  80. package/src/packlets/iana/common/model.ts +56 -0
  81. package/src/packlets/iana/common/registeredItems.ts +145 -0
  82. package/src/packlets/iana/common/utils.ts +32 -0
  83. package/src/packlets/iana/common/validate.ts +64 -0
  84. package/src/packlets/iana/converters.ts +26 -0
  85. package/src/packlets/iana/defaultRegistries.ts +40 -0
  86. package/src/packlets/iana/index.ts +33 -0
  87. package/src/packlets/iana/jar/converters.ts +26 -0
  88. package/src/packlets/iana/jar/index.ts +27 -0
  89. package/src/packlets/iana/jar/jarConverters.ts +70 -0
  90. package/src/packlets/iana/jar/jarModel.ts +34 -0
  91. package/src/packlets/iana/jar/language-subtags/converters.ts +26 -0
  92. package/src/packlets/iana/jar/language-subtags/index.ts +27 -0
  93. package/src/packlets/iana/jar/language-subtags/model.ts +26 -0
  94. package/src/packlets/iana/jar/language-subtags/registry/converters.ts +40 -0
  95. package/src/packlets/iana/jar/language-subtags/registry/index.ts +26 -0
  96. package/src/packlets/iana/jar/language-subtags/registry/model.ts +171 -0
  97. package/src/packlets/iana/jar/language-subtags/tags/converters.ts +120 -0
  98. package/src/packlets/iana/jar/language-subtags/tags/index.ts +28 -0
  99. package/src/packlets/iana/jar/language-subtags/tags/model.ts +71 -0
  100. package/src/packlets/iana/jar/language-subtags/tags/tagValidation.ts +67 -0
  101. package/src/packlets/iana/jar/language-subtags/tags/validate.ts +106 -0
  102. package/src/packlets/iana/jar/model.ts +26 -0
  103. package/src/packlets/iana/language-subtags/common.ts +46 -0
  104. package/src/packlets/iana/language-subtags/converters.ts +226 -0
  105. package/src/packlets/iana/language-subtags/index.ts +30 -0
  106. package/src/packlets/iana/language-subtags/jarConverters.ts +269 -0
  107. package/src/packlets/iana/language-subtags/model.ts +213 -0
  108. package/src/packlets/iana/language-subtags/scope.ts +222 -0
  109. package/src/packlets/iana/language-subtags/subtagRegistry.ts +136 -0
  110. package/src/packlets/iana/language-subtags/validate.ts +23 -0
  111. package/src/packlets/iana/language-tag-extensions/converters.ts +71 -0
  112. package/src/packlets/iana/language-tag-extensions/extensionsRegistry.ts +92 -0
  113. package/src/packlets/iana/language-tag-extensions/extensionsScope.ts +60 -0
  114. package/src/packlets/iana/language-tag-extensions/index.ts +29 -0
  115. package/src/packlets/iana/language-tag-extensions/jarConverters.ts +91 -0
  116. package/src/packlets/iana/language-tag-extensions/model.ts +67 -0
  117. package/src/packlets/iana/language-tag-extensions/validate.ts +36 -0
  118. package/src/packlets/iana/languageRegistries.ts +57 -0
  119. package/src/packlets/iana/model.ts +26 -0
  120. package/src/packlets/iana/validate.ts +23 -0
  121. package/src/packlets/unsd/areas.ts +105 -0
  122. package/src/packlets/unsd/common.ts +79 -0
  123. package/src/packlets/unsd/csv/converters.ts +82 -0
  124. package/src/packlets/unsd/csv/index.ts +26 -0
  125. package/src/packlets/unsd/csv/model.ts +44 -0
  126. package/src/packlets/unsd/defaultRegistries.ts +40 -0
  127. package/src/packlets/unsd/index.ts +28 -0
  128. package/src/packlets/unsd/regionCodes.ts +144 -0
  129. package/src/packlets/unsd/regions.ts +95 -0
  130. package/src/packlets/utils/index.ts +24 -0
  131. package/src/packlets/utils/jsonHelpers.ts +25 -0
  132. package/src/packlets/utils/public.ts +28 -0
  133. package/src/packlets/utils/validationHelpers.ts +180 -0
  134. package/CHANGELOG.md +0 -109
  135. package/lib/index.d.ts.map +0 -1
  136. package/lib/index.js.map +0 -1
  137. package/lib/packlets/bcp47/bcp47Subtags/converters.d.ts.map +0 -1
  138. package/lib/packlets/bcp47/bcp47Subtags/converters.js.map +0 -1
  139. package/lib/packlets/bcp47/bcp47Subtags/index.d.ts.map +0 -1
  140. package/lib/packlets/bcp47/bcp47Subtags/index.js.map +0 -1
  141. package/lib/packlets/bcp47/bcp47Subtags/model.d.ts.map +0 -1
  142. package/lib/packlets/bcp47/bcp47Subtags/model.js.map +0 -1
  143. package/lib/packlets/bcp47/bcp47Subtags/validate.d.ts.map +0 -1
  144. package/lib/packlets/bcp47/bcp47Subtags/validate.js.map +0 -1
  145. package/lib/packlets/bcp47/common.d.ts.map +0 -1
  146. package/lib/packlets/bcp47/common.js.map +0 -1
  147. package/lib/packlets/bcp47/helpers.d.ts.map +0 -1
  148. package/lib/packlets/bcp47/helpers.js.map +0 -1
  149. package/lib/packlets/bcp47/index.d.ts.map +0 -1
  150. package/lib/packlets/bcp47/index.js.map +0 -1
  151. package/lib/packlets/bcp47/languageRegistryData.d.ts.map +0 -1
  152. package/lib/packlets/bcp47/languageRegistryData.js.map +0 -1
  153. package/lib/packlets/bcp47/languageTag.d.ts.map +0 -1
  154. package/lib/packlets/bcp47/languageTag.js.map +0 -1
  155. package/lib/packlets/bcp47/languageTagParser.d.ts.map +0 -1
  156. package/lib/packlets/bcp47/languageTagParser.js.map +0 -1
  157. package/lib/packlets/bcp47/match/chooser.d.ts.map +0 -1
  158. package/lib/packlets/bcp47/match/chooser.js.map +0 -1
  159. package/lib/packlets/bcp47/match/common.d.ts.map +0 -1
  160. package/lib/packlets/bcp47/match/common.js.map +0 -1
  161. package/lib/packlets/bcp47/match/index.d.ts.map +0 -1
  162. package/lib/packlets/bcp47/match/index.js.map +0 -1
  163. package/lib/packlets/bcp47/match/similarity.d.ts.map +0 -1
  164. package/lib/packlets/bcp47/match/similarity.js.map +0 -1
  165. package/lib/packlets/bcp47/normalization/baseNormalizer.d.ts.map +0 -1
  166. package/lib/packlets/bcp47/normalization/baseNormalizer.js.map +0 -1
  167. package/lib/packlets/bcp47/normalization/canonicalNormalizer.d.ts.map +0 -1
  168. package/lib/packlets/bcp47/normalization/canonicalNormalizer.js.map +0 -1
  169. package/lib/packlets/bcp47/normalization/common.d.ts.map +0 -1
  170. package/lib/packlets/bcp47/normalization/common.js.map +0 -1
  171. package/lib/packlets/bcp47/normalization/index.d.ts.map +0 -1
  172. package/lib/packlets/bcp47/normalization/index.js.map +0 -1
  173. package/lib/packlets/bcp47/normalization/normalizeTag.d.ts.map +0 -1
  174. package/lib/packlets/bcp47/normalization/normalizeTag.js.map +0 -1
  175. package/lib/packlets/bcp47/normalization/preferredTagNormalizer.d.ts.map +0 -1
  176. package/lib/packlets/bcp47/normalization/preferredTagNormalizer.js.map +0 -1
  177. package/lib/packlets/bcp47/overrides/converters.d.ts.map +0 -1
  178. package/lib/packlets/bcp47/overrides/converters.js.map +0 -1
  179. package/lib/packlets/bcp47/overrides/defaultRegistries.d.ts.map +0 -1
  180. package/lib/packlets/bcp47/overrides/defaultRegistries.js.map +0 -1
  181. package/lib/packlets/bcp47/overrides/index.d.ts.map +0 -1
  182. package/lib/packlets/bcp47/overrides/index.js.map +0 -1
  183. package/lib/packlets/bcp47/overrides/model.d.ts.map +0 -1
  184. package/lib/packlets/bcp47/overrides/model.js.map +0 -1
  185. package/lib/packlets/bcp47/overrides/overridesRegistry.d.ts.map +0 -1
  186. package/lib/packlets/bcp47/overrides/overridesRegistry.js.map +0 -1
  187. package/lib/packlets/bcp47/validation/baseValidator.d.ts.map +0 -1
  188. package/lib/packlets/bcp47/validation/baseValidator.js.map +0 -1
  189. package/lib/packlets/bcp47/validation/common.d.ts.map +0 -1
  190. package/lib/packlets/bcp47/validation/common.js.map +0 -1
  191. package/lib/packlets/bcp47/validation/index.d.ts.map +0 -1
  192. package/lib/packlets/bcp47/validation/index.js.map +0 -1
  193. package/lib/packlets/bcp47/validation/isCanonical.d.ts.map +0 -1
  194. package/lib/packlets/bcp47/validation/isCanonical.js.map +0 -1
  195. package/lib/packlets/bcp47/validation/isInPreferredForm.d.ts.map +0 -1
  196. package/lib/packlets/bcp47/validation/isInPreferredForm.js.map +0 -1
  197. package/lib/packlets/bcp47/validation/isStrictlyValid.d.ts.map +0 -1
  198. package/lib/packlets/bcp47/validation/isStrictlyValid.js.map +0 -1
  199. package/lib/packlets/bcp47/validation/isValid.d.ts.map +0 -1
  200. package/lib/packlets/bcp47/validation/isValid.js.map +0 -1
  201. package/lib/packlets/bcp47/validation/isWellFormed.d.ts.map +0 -1
  202. package/lib/packlets/bcp47/validation/isWellFormed.js.map +0 -1
  203. package/lib/packlets/bcp47/validation/validateTag.d.ts.map +0 -1
  204. package/lib/packlets/bcp47/validation/validateTag.js.map +0 -1
  205. package/lib/packlets/iana/common/converters.d.ts.map +0 -1
  206. package/lib/packlets/iana/common/converters.js.map +0 -1
  207. package/lib/packlets/iana/common/model.d.ts.map +0 -1
  208. package/lib/packlets/iana/common/model.js.map +0 -1
  209. package/lib/packlets/iana/common/registeredItems.d.ts.map +0 -1
  210. package/lib/packlets/iana/common/registeredItems.js.map +0 -1
  211. package/lib/packlets/iana/common/utils.d.ts.map +0 -1
  212. package/lib/packlets/iana/common/utils.js.map +0 -1
  213. package/lib/packlets/iana/common/validate.d.ts.map +0 -1
  214. package/lib/packlets/iana/common/validate.js.map +0 -1
  215. package/lib/packlets/iana/converters.d.ts.map +0 -1
  216. package/lib/packlets/iana/converters.js.map +0 -1
  217. package/lib/packlets/iana/defaultRegistries.d.ts.map +0 -1
  218. package/lib/packlets/iana/defaultRegistries.js.map +0 -1
  219. package/lib/packlets/iana/index.d.ts.map +0 -1
  220. package/lib/packlets/iana/index.js.map +0 -1
  221. package/lib/packlets/iana/jar/converters.d.ts.map +0 -1
  222. package/lib/packlets/iana/jar/converters.js.map +0 -1
  223. package/lib/packlets/iana/jar/index.d.ts.map +0 -1
  224. package/lib/packlets/iana/jar/index.js.map +0 -1
  225. package/lib/packlets/iana/jar/jarConverters.d.ts.map +0 -1
  226. package/lib/packlets/iana/jar/jarConverters.js.map +0 -1
  227. package/lib/packlets/iana/jar/jarModel.d.ts.map +0 -1
  228. package/lib/packlets/iana/jar/jarModel.js.map +0 -1
  229. package/lib/packlets/iana/jar/language-subtags/converters.d.ts.map +0 -1
  230. package/lib/packlets/iana/jar/language-subtags/converters.js.map +0 -1
  231. package/lib/packlets/iana/jar/language-subtags/index.d.ts.map +0 -1
  232. package/lib/packlets/iana/jar/language-subtags/index.js.map +0 -1
  233. package/lib/packlets/iana/jar/language-subtags/model.d.ts.map +0 -1
  234. package/lib/packlets/iana/jar/language-subtags/model.js.map +0 -1
  235. package/lib/packlets/iana/jar/language-subtags/registry/converters.d.ts.map +0 -1
  236. package/lib/packlets/iana/jar/language-subtags/registry/converters.js.map +0 -1
  237. package/lib/packlets/iana/jar/language-subtags/registry/index.d.ts.map +0 -1
  238. package/lib/packlets/iana/jar/language-subtags/registry/index.js.map +0 -1
  239. package/lib/packlets/iana/jar/language-subtags/registry/model.d.ts.map +0 -1
  240. package/lib/packlets/iana/jar/language-subtags/registry/model.js.map +0 -1
  241. package/lib/packlets/iana/jar/language-subtags/tags/converters.d.ts.map +0 -1
  242. package/lib/packlets/iana/jar/language-subtags/tags/converters.js.map +0 -1
  243. package/lib/packlets/iana/jar/language-subtags/tags/index.d.ts.map +0 -1
  244. package/lib/packlets/iana/jar/language-subtags/tags/index.js.map +0 -1
  245. package/lib/packlets/iana/jar/language-subtags/tags/model.d.ts.map +0 -1
  246. package/lib/packlets/iana/jar/language-subtags/tags/model.js.map +0 -1
  247. package/lib/packlets/iana/jar/language-subtags/tags/tagValidation.d.ts.map +0 -1
  248. package/lib/packlets/iana/jar/language-subtags/tags/tagValidation.js.map +0 -1
  249. package/lib/packlets/iana/jar/language-subtags/tags/validate.d.ts.map +0 -1
  250. package/lib/packlets/iana/jar/language-subtags/tags/validate.js.map +0 -1
  251. package/lib/packlets/iana/jar/model.d.ts.map +0 -1
  252. package/lib/packlets/iana/jar/model.js.map +0 -1
  253. package/lib/packlets/iana/language-subtags/common.d.ts.map +0 -1
  254. package/lib/packlets/iana/language-subtags/common.js.map +0 -1
  255. package/lib/packlets/iana/language-subtags/converters.d.ts.map +0 -1
  256. package/lib/packlets/iana/language-subtags/converters.js.map +0 -1
  257. package/lib/packlets/iana/language-subtags/index.d.ts.map +0 -1
  258. package/lib/packlets/iana/language-subtags/index.js.map +0 -1
  259. package/lib/packlets/iana/language-subtags/jarConverters.d.ts.map +0 -1
  260. package/lib/packlets/iana/language-subtags/jarConverters.js.map +0 -1
  261. package/lib/packlets/iana/language-subtags/model.d.ts.map +0 -1
  262. package/lib/packlets/iana/language-subtags/model.js.map +0 -1
  263. package/lib/packlets/iana/language-subtags/scope.d.ts.map +0 -1
  264. package/lib/packlets/iana/language-subtags/scope.js.map +0 -1
  265. package/lib/packlets/iana/language-subtags/subtagRegistry.d.ts.map +0 -1
  266. package/lib/packlets/iana/language-subtags/subtagRegistry.js.map +0 -1
  267. package/lib/packlets/iana/language-subtags/validate.d.ts.map +0 -1
  268. package/lib/packlets/iana/language-subtags/validate.js.map +0 -1
  269. package/lib/packlets/iana/language-tag-extensions/converters.d.ts.map +0 -1
  270. package/lib/packlets/iana/language-tag-extensions/converters.js.map +0 -1
  271. package/lib/packlets/iana/language-tag-extensions/extensionsRegistry.d.ts.map +0 -1
  272. package/lib/packlets/iana/language-tag-extensions/extensionsRegistry.js.map +0 -1
  273. package/lib/packlets/iana/language-tag-extensions/extensionsScope.d.ts.map +0 -1
  274. package/lib/packlets/iana/language-tag-extensions/extensionsScope.js.map +0 -1
  275. package/lib/packlets/iana/language-tag-extensions/index.d.ts.map +0 -1
  276. package/lib/packlets/iana/language-tag-extensions/index.js.map +0 -1
  277. package/lib/packlets/iana/language-tag-extensions/jarConverters.d.ts.map +0 -1
  278. package/lib/packlets/iana/language-tag-extensions/jarConverters.js.map +0 -1
  279. package/lib/packlets/iana/language-tag-extensions/model.d.ts.map +0 -1
  280. package/lib/packlets/iana/language-tag-extensions/model.js.map +0 -1
  281. package/lib/packlets/iana/language-tag-extensions/validate.d.ts.map +0 -1
  282. package/lib/packlets/iana/language-tag-extensions/validate.js.map +0 -1
  283. package/lib/packlets/iana/languageRegistries.d.ts.map +0 -1
  284. package/lib/packlets/iana/languageRegistries.js.map +0 -1
  285. package/lib/packlets/iana/model.d.ts.map +0 -1
  286. package/lib/packlets/iana/model.js.map +0 -1
  287. package/lib/packlets/iana/validate.d.ts.map +0 -1
  288. package/lib/packlets/iana/validate.js.map +0 -1
  289. package/lib/packlets/unsd/areas.d.ts.map +0 -1
  290. package/lib/packlets/unsd/areas.js.map +0 -1
  291. package/lib/packlets/unsd/common.d.ts.map +0 -1
  292. package/lib/packlets/unsd/common.js.map +0 -1
  293. package/lib/packlets/unsd/csv/converters.d.ts.map +0 -1
  294. package/lib/packlets/unsd/csv/converters.js.map +0 -1
  295. package/lib/packlets/unsd/csv/index.d.ts.map +0 -1
  296. package/lib/packlets/unsd/csv/index.js.map +0 -1
  297. package/lib/packlets/unsd/csv/model.d.ts.map +0 -1
  298. package/lib/packlets/unsd/csv/model.js.map +0 -1
  299. package/lib/packlets/unsd/defaultRegistries.d.ts.map +0 -1
  300. package/lib/packlets/unsd/defaultRegistries.js.map +0 -1
  301. package/lib/packlets/unsd/index.d.ts.map +0 -1
  302. package/lib/packlets/unsd/index.js.map +0 -1
  303. package/lib/packlets/unsd/regionCodes.d.ts.map +0 -1
  304. package/lib/packlets/unsd/regionCodes.js.map +0 -1
  305. package/lib/packlets/unsd/regions.d.ts.map +0 -1
  306. package/lib/packlets/unsd/regions.js.map +0 -1
  307. package/lib/packlets/utils/index.d.ts.map +0 -1
  308. package/lib/packlets/utils/index.js.map +0 -1
  309. package/lib/packlets/utils/jsonHelpers.d.ts.map +0 -1
  310. package/lib/packlets/utils/jsonHelpers.js.map +0 -1
  311. package/lib/packlets/utils/public.d.ts.map +0 -1
  312. package/lib/packlets/utils/public.js.map +0 -1
  313. package/lib/packlets/utils/validationHelpers.d.ts.map +0 -1
  314. package/lib/packlets/utils/validationHelpers.js.map +0 -1
@@ -0,0 +1,243 @@
1
+ /*
2
+ * Copyright (c) 2022 Erik Fortune
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+ import * as Iana from '../../iana';
24
+ import * as Unsd from '../../unsd';
25
+
26
+ import { DefaultRegistries, OverridesRegistry } from '../overrides';
27
+
28
+ import { GlobalRegion } from '../common';
29
+ import { LanguageTag } from '../languageTag';
30
+ import { tagSimilarity } from './common';
31
+
32
+ /**
33
+ * Helper to compare two language tags to determine how closely related they are,
34
+ * applying normalization and language semantics as appropriate.
35
+ * @public
36
+ */
37
+ export class LanguageSimilarityMatcher {
38
+ public iana: Iana.LanguageRegistries;
39
+ public unsd: Unsd.RegionCodes;
40
+ public overrides: OverridesRegistry;
41
+
42
+ public constructor(iana?: Iana.LanguageRegistries) {
43
+ /* c8 ignore next */
44
+ this.iana = iana ?? Iana.DefaultRegistries.languageRegistries;
45
+ this.unsd = Unsd.DefaultRegistries.regionCodes;
46
+ this.overrides = DefaultRegistries.overridesRegistry;
47
+ }
48
+
49
+ public matchLanguageTags(t1: LanguageTag, t2: LanguageTag): number {
50
+ // no primary tag is either all private or grandfathered, which must match
51
+ // exactly.
52
+ if (!t1.subtags.primaryLanguage || !t2.subtags.primaryLanguage) {
53
+ return t1.toString().toLowerCase() === t2.toString().toLowerCase()
54
+ ? tagSimilarity.exact
55
+ : tagSimilarity.none;
56
+ }
57
+
58
+ let quality = this.matchPrimaryLanguage(t1, t2);
59
+ quality = quality > tagSimilarity.none ? Math.min(this.matchExtlang(t1, t2), quality) : quality;
60
+ quality = quality > tagSimilarity.none ? Math.min(this.matchScript(t1, t2), quality) : quality;
61
+ quality = quality > tagSimilarity.none ? Math.min(this.matchRegion(t1, t2), quality) : quality;
62
+ quality = quality > tagSimilarity.none ? Math.min(this.matchVariants(t1, t2), quality) : quality;
63
+ quality = quality > tagSimilarity.none ? Math.min(this.matchExtensions(t1, t2), quality) : quality;
64
+ quality = quality > tagSimilarity.none ? Math.min(this.matchPrivateUseTags(t1, t2), quality) : quality;
65
+
66
+ return quality;
67
+ }
68
+
69
+ public matchPrimaryLanguage(lt1: LanguageTag, lt2: LanguageTag): number {
70
+ /* c8 ignore next 2 */
71
+ const l1 = lt1.subtags.primaryLanguage?.toLowerCase();
72
+ const l2 = lt2.subtags.primaryLanguage?.toLowerCase();
73
+
74
+ if (l1 === l2) {
75
+ return tagSimilarity.exact;
76
+ }
77
+
78
+ if (lt1.isUndetermined || lt2.isUndetermined) {
79
+ return tagSimilarity.undetermined;
80
+ }
81
+
82
+ return tagSimilarity.none;
83
+ }
84
+
85
+ public matchExtlang(lt1: LanguageTag, lt2: LanguageTag): number {
86
+ if (lt1.subtags.extlangs?.length !== lt2.subtags.extlangs?.length) {
87
+ return tagSimilarity.none;
88
+ }
89
+
90
+ if (lt1.subtags.extlangs) {
91
+ for (let i = 0; i < lt1.subtags.extlangs.length; i++) {
92
+ if (lt1.subtags.extlangs[i].toLowerCase() !== lt2.subtags.extlangs![i].toLowerCase()) {
93
+ return tagSimilarity.none;
94
+ }
95
+ }
96
+ }
97
+
98
+ return tagSimilarity.exact;
99
+ }
100
+
101
+ public matchScript(lt1: LanguageTag, lt2: LanguageTag): number {
102
+ const s1 = lt1.effectiveScript?.toLowerCase();
103
+ const s2 = lt2.effectiveScript?.toLowerCase();
104
+
105
+ if (s1 === s2) {
106
+ return tagSimilarity.exact;
107
+ }
108
+
109
+ if (lt1.isUndetermined || lt2.isUndetermined) {
110
+ return tagSimilarity.undetermined;
111
+ }
112
+
113
+ return tagSimilarity.none;
114
+ }
115
+
116
+ public matchRegion(lt1: LanguageTag, lt2: LanguageTag): number {
117
+ const r1 = lt1.subtags.region?.toUpperCase() as Iana.LanguageSubtags.RegionSubtag;
118
+ const r2 = lt2.subtags.region?.toUpperCase() as Iana.LanguageSubtags.RegionSubtag;
119
+
120
+ if (r1 === r2) {
121
+ return tagSimilarity.exact;
122
+ }
123
+
124
+ // region 001 is equivalent to neutral (no region)
125
+ if (r1 === GlobalRegion || r2 === GlobalRegion) {
126
+ // if one tag is 001 and the other in neutral, exact match
127
+ // otherwise, one tag is 001 so neutral region match
128
+ return !r1 || !r2 ? tagSimilarity.exact : tagSimilarity.neutralRegion;
129
+ }
130
+
131
+ if (!r1 || !r2) {
132
+ return tagSimilarity.neutralRegion;
133
+ }
134
+
135
+ // macro-region match
136
+ const r1IsMacroRegion = Iana.Validate.unM49RegionCode.isWellFormed(r1);
137
+ const r2IsMacroRegion = Iana.Validate.unM49RegionCode.isWellFormed(r2);
138
+ if (r1IsMacroRegion || r2IsMacroRegion) {
139
+ let contained: Unsd.ICountryOrArea | Unsd.Region | undefined;
140
+ let container: Unsd.Region | undefined;
141
+ if (r1IsMacroRegion) {
142
+ container = this.unsd.regions.tryGetRegion(r1 as unknown as Iana.Model.UnM49RegionCode);
143
+ contained =
144
+ this.unsd.areas.tryGetAlpha2Area(r2 as unknown as Iana.Model.IsoAlpha2RegionCode) ??
145
+ this.unsd.tryGetRegionOrArea(r2 as unknown as Iana.Model.UnM49RegionCode);
146
+ } else {
147
+ container = this.unsd.regions.tryGetRegion(r2 as unknown as Iana.Model.UnM49RegionCode);
148
+ contained = this.unsd.areas.tryGetAlpha2Area(r1 as unknown as Iana.Model.IsoAlpha2RegionCode);
149
+ }
150
+ if (container && contained) {
151
+ if (this.unsd.getIsContained(container, contained)) {
152
+ return tagSimilarity.macroRegion;
153
+ }
154
+
155
+ // if they're both regions, also check to see if the second region contains the
156
+ // first
157
+ if (contained.tier !== 'area' && this.unsd.getIsContained(contained, container)) {
158
+ return tagSimilarity.macroRegion;
159
+ }
160
+ }
161
+ }
162
+
163
+ /* c8 ignore next 6 */
164
+ const o1 = this.overrides.overrides.get(
165
+ lt1.subtags.primaryLanguage?.toLowerCase() as Iana.LanguageSubtags.LanguageSubtag
166
+ );
167
+ const o2 = this.overrides.overrides.get(
168
+ lt2.subtags.primaryLanguage?.toLowerCase() as Iana.LanguageSubtags.LanguageSubtag
169
+ );
170
+
171
+ // orthographic affinity
172
+ if (o1 && o2) {
173
+ /* c8 ignore next 2 */
174
+ const a1 = o1.affinity?.get(r1) ?? o1.defaultAffinity;
175
+ const a2 = o2.affinity?.get(r2) ?? o2.defaultAffinity;
176
+ if (a1 && a2 && a1 === a2) {
177
+ if (r1 === a1.toUpperCase() || r2 === a2.toUpperCase()) {
178
+ return tagSimilarity.preferredAffinity;
179
+ }
180
+ return tagSimilarity.affinity;
181
+ }
182
+ }
183
+
184
+ // preferred region
185
+ if (o1?.preferredRegion === r1 || o2?.preferredRegion === r2) {
186
+ return tagSimilarity.preferredRegion;
187
+ }
188
+
189
+ return tagSimilarity.sibling;
190
+ }
191
+
192
+ public matchVariants(lt1: LanguageTag, lt2: LanguageTag): number {
193
+ if (lt1.subtags.variants?.length !== lt2.subtags.variants?.length) {
194
+ return tagSimilarity.region;
195
+ }
196
+
197
+ if (lt1.subtags.variants) {
198
+ for (let i = 0; i < lt1.subtags.variants.length; i++) {
199
+ if (lt1.subtags.variants[i].toLowerCase() !== lt2.subtags.variants![i].toLowerCase()) {
200
+ return tagSimilarity.region;
201
+ }
202
+ }
203
+ }
204
+
205
+ return tagSimilarity.exact;
206
+ }
207
+
208
+ public matchExtensions(lt1: LanguageTag, lt2: LanguageTag): number {
209
+ if (lt1.subtags.extensions?.length !== lt2.subtags.extensions?.length) {
210
+ return tagSimilarity.variant;
211
+ }
212
+
213
+ if (lt1.subtags.extensions) {
214
+ for (let i = 0; i < lt1.subtags.extensions.length; i++) {
215
+ if (
216
+ lt1.subtags.extensions[i].singleton.toLowerCase() !==
217
+ lt2.subtags.extensions![i].singleton.toLowerCase() ||
218
+ lt1.subtags.extensions[i].value.toLowerCase() !== lt2.subtags.extensions![i].value.toLowerCase()
219
+ ) {
220
+ return tagSimilarity.variant;
221
+ }
222
+ }
223
+ }
224
+
225
+ return tagSimilarity.exact;
226
+ }
227
+
228
+ public matchPrivateUseTags(lt1: LanguageTag, lt2: LanguageTag): number {
229
+ if (lt1.subtags.privateUse?.length !== lt2.subtags.privateUse?.length) {
230
+ return tagSimilarity.variant;
231
+ }
232
+
233
+ if (lt1.subtags.privateUse) {
234
+ for (let i = 0; i < lt1.subtags.privateUse.length; i++) {
235
+ if (lt1.subtags.privateUse[i].toLowerCase() !== lt2.subtags.privateUse![i].toLowerCase()) {
236
+ return tagSimilarity.variant;
237
+ }
238
+ }
239
+ }
240
+
241
+ return tagSimilarity.exact;
242
+ }
243
+ }
@@ -0,0 +1,146 @@
1
+ /*
2
+ * Copyright (c) 2022 Erik Fortune
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+ import * as Iana from '../../iana';
24
+
25
+ import { Result, allSucceed, fail, mapResults, populateObject, succeed } from '@fgv/ts-utils';
26
+ import { ExtensionSingleton, ExtensionSubtag } from '../bcp47Subtags/model';
27
+ import { IExtensionSubtagValue, ISubtags, subtagsToString } from '../common';
28
+ import { TagNormalization } from './common';
29
+
30
+ /**
31
+ * @public
32
+ */
33
+ export interface ITagNormalizer {
34
+ readonly normalization: TagNormalization;
35
+
36
+ processSubtags(subtags: ISubtags): Result<ISubtags>;
37
+ }
38
+
39
+ /**
40
+ * @public
41
+ */
42
+ export abstract class TagNormalizerBase {
43
+ protected readonly _iana: Iana.LanguageRegistries;
44
+
45
+ public abstract readonly normalization: TagNormalization;
46
+
47
+ public constructor(iana?: Iana.LanguageRegistries) {
48
+ /* c8 ignore next - dependency injection primarily for test */
49
+ this._iana = iana ?? Iana.DefaultRegistries.languageRegistries;
50
+ }
51
+
52
+ public processSubtags(subtags: ISubtags): Result<ISubtags> {
53
+ return populateObject<ISubtags>(
54
+ {
55
+ primaryLanguage: () => this._processLanguage(subtags),
56
+ extlangs: () => this._processExtlangs(subtags),
57
+ script: () => this._processScript(subtags),
58
+ region: () => this._processRegion(subtags),
59
+ variants: () => this._processVariants(subtags),
60
+ extensions: () => this._processExtensions(subtags),
61
+ privateUse: () => this._processPrivateUseTags(subtags),
62
+ grandfathered: () => this._processGrandfatheredTags(subtags)
63
+ },
64
+ { suppressUndefined: true }
65
+ ).onSuccess((processed) => {
66
+ return this._postValidate(processed);
67
+ });
68
+ }
69
+
70
+ protected _basicPostValidation(subtags: ISubtags): Result<ISubtags> {
71
+ /* c8 ignore next 7 - any validation whatsoever catches these so should never happen in practice */
72
+ if (
73
+ subtags.primaryLanguage === undefined &&
74
+ subtags.grandfathered === undefined &&
75
+ subtags.privateUse === undefined
76
+ ) {
77
+ return fail(`${subtagsToString(subtags)}: missing primary language subtag.`);
78
+ }
79
+
80
+ /* c8 ignore next 3 - any validation whatsoever catches these so should never happen in practice */
81
+ if (subtags.extlangs && subtags.extlangs.length > 3) {
82
+ return fail(`${subtagsToString(subtags)}: too many extlang subtags`);
83
+ }
84
+ return succeed(subtags);
85
+ }
86
+
87
+ protected _postValidate(subtags: ISubtags): Result<ISubtags> {
88
+ return this._basicPostValidation(subtags);
89
+ }
90
+
91
+ protected _processExtensions(subtags: ISubtags): Result<IExtensionSubtagValue[] | undefined> {
92
+ if (subtags.extensions) {
93
+ return mapResults(
94
+ subtags.extensions.map((ex) => {
95
+ return populateObject<IExtensionSubtagValue>({
96
+ singleton: () => this._processExtensionSingleton(ex.singleton),
97
+ value: () => this._processExtensionSubtagValue(ex.value)
98
+ });
99
+ })
100
+ );
101
+ }
102
+ return succeed(subtags.extensions);
103
+ }
104
+
105
+ protected _verifyUnique<T, TK extends string>(
106
+ description: string,
107
+ items: T[] | undefined,
108
+ getKey: (item: T) => TK
109
+ ): Result<T[] | undefined> {
110
+ if (items) {
111
+ const present = new Set<TK>();
112
+ return allSucceed(
113
+ items.map((i) => {
114
+ const key = getKey(i);
115
+ if (present.has(key)) {
116
+ return fail(`${key}: duplicate ${description}`);
117
+ }
118
+ present.add(key);
119
+ return succeed(key);
120
+ }),
121
+ items
122
+ );
123
+ }
124
+ return succeed(items);
125
+ }
126
+
127
+ protected abstract _processLanguage(
128
+ subtags: ISubtags
129
+ ): Result<Iana.LanguageSubtags.LanguageSubtag | undefined>;
130
+ protected abstract _processExtlangs(
131
+ subtags: ISubtags
132
+ ): Result<Iana.LanguageSubtags.ExtLangSubtag[] | undefined>;
133
+ protected abstract _processScript(subtags: ISubtags): Result<Iana.LanguageSubtags.ScriptSubtag | undefined>;
134
+ protected abstract _processRegion(subtags: ISubtags): Result<Iana.LanguageSubtags.RegionSubtag | undefined>;
135
+ protected abstract _processVariants(
136
+ subtags: ISubtags
137
+ ): Result<Iana.LanguageSubtags.VariantSubtag[] | undefined>;
138
+ protected abstract _processExtensionSingleton(singleton: ExtensionSingleton): Result<ExtensionSingleton>;
139
+ protected abstract _processExtensionSubtagValue(value: ExtensionSubtag): Result<ExtensionSubtag>;
140
+ protected abstract _processPrivateUseTags(
141
+ subtags: ISubtags
142
+ ): Result<Iana.LanguageSubtags.ExtendedLanguageRange[] | undefined>;
143
+ protected abstract _processGrandfatheredTags(
144
+ subtags: ISubtags
145
+ ): Result<Iana.LanguageSubtags.GrandfatheredTag | undefined>;
146
+ }
@@ -0,0 +1,102 @@
1
+ /*
2
+ * Copyright (c) 2022 Erik Fortune
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+ import * as Iana from '../../iana';
24
+ import * as Bcp47Subtags from '../bcp47Subtags';
25
+
26
+ import { Result, mapResults, succeed } from '@fgv/ts-utils';
27
+
28
+ import { ExtensionSingleton, ExtensionSubtag } from '../bcp47Subtags/model';
29
+ import { ISubtags } from '../common';
30
+ import { TagNormalizerBase } from './baseNormalizer';
31
+ import { TagNormalization } from './common';
32
+
33
+ /**
34
+ * @internal
35
+ */
36
+ export class CanonicalNormalizer extends TagNormalizerBase {
37
+ public readonly normalization: TagNormalization = 'canonical';
38
+
39
+ protected _processLanguage(subtags: ISubtags): Result<Iana.LanguageSubtags.LanguageSubtag | undefined> {
40
+ if (subtags.primaryLanguage) {
41
+ return this._iana.subtags.languages.toCanonical(subtags.primaryLanguage);
42
+ }
43
+ return succeed(subtags.primaryLanguage);
44
+ }
45
+
46
+ protected _processExtlangs(subtags: ISubtags): Result<Iana.LanguageSubtags.ExtLangSubtag[] | undefined> {
47
+ if (subtags.extlangs) {
48
+ return mapResults(subtags.extlangs.map((e) => this._iana.subtags.extlangs.toCanonical(e)));
49
+ }
50
+ return succeed(undefined);
51
+ }
52
+
53
+ protected _processScript(subtags: ISubtags): Result<Iana.LanguageSubtags.ScriptSubtag | undefined> {
54
+ if (subtags.script) {
55
+ return this._iana.subtags.scripts.toCanonical(subtags.script);
56
+ }
57
+ return succeed(undefined);
58
+ }
59
+
60
+ protected _processRegion(subtags: ISubtags): Result<Iana.LanguageSubtags.RegionSubtag | undefined> {
61
+ if (subtags.region) {
62
+ return this._iana.subtags.regions.toCanonical(subtags.region);
63
+ }
64
+ return succeed(undefined);
65
+ }
66
+
67
+ protected _processVariants(subtags: ISubtags): Result<Iana.LanguageSubtags.VariantSubtag[] | undefined> {
68
+ if (subtags.variants) {
69
+ return mapResults(subtags.variants.map((v) => this._iana.subtags.variants.toCanonical(v)));
70
+ }
71
+ return succeed(undefined);
72
+ }
73
+
74
+ protected _processExtensionSingleton(singleton: ExtensionSingleton): Result<ExtensionSingleton> {
75
+ return this._iana.extensions.extensions.toCanonical(singleton);
76
+ }
77
+
78
+ protected _processExtensionSubtagValue(value: ExtensionSubtag): Result<ExtensionSubtag> {
79
+ return Bcp47Subtags.Validate.extensionSubtag.toCanonical(value);
80
+ }
81
+
82
+ protected _processPrivateUseTags(
83
+ subtags: ISubtags
84
+ ): Result<Iana.LanguageSubtags.ExtendedLanguageRange[] | undefined> {
85
+ if (subtags.privateUse) {
86
+ const merged = subtags.privateUse.join('-');
87
+ return Iana.LanguageSubtags.Validate.extendedLanguageRange.toCanonical(merged).onSuccess((canon) => {
88
+ return succeed(canon.split('-') as Iana.LanguageSubtags.ExtendedLanguageRange[]);
89
+ });
90
+ }
91
+ return succeed(subtags.privateUse);
92
+ }
93
+
94
+ protected _processGrandfatheredTags(
95
+ subtags: ISubtags
96
+ ): Result<Iana.LanguageSubtags.GrandfatheredTag | undefined> {
97
+ if (subtags.grandfathered) {
98
+ return this._iana.subtags.grandfathered.toCanonical(subtags.grandfathered);
99
+ }
100
+ return succeed(undefined);
101
+ }
102
+ }
@@ -0,0 +1,84 @@
1
+ /*
2
+ * Copyright (c) 2022 Erik Fortune
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+ /**
24
+ * Describes the degree of normalization of a language tag.
25
+ * @public
26
+ */
27
+ export type TagNormalization = 'unknown' | 'none' | 'canonical' | 'preferred';
28
+
29
+ /**
30
+ * Ordered ranking of the degrees of normalization, from `unknown` (least
31
+ * normalized) to `preferred` (most normalized).
32
+ * @public
33
+ */
34
+ const normalizationRank: Record<TagNormalization, number> = {
35
+ /**
36
+ * Normalization level is unknown.
37
+ */
38
+ unknown: 0,
39
+ /**
40
+ * Not normalized.
41
+ */
42
+ none: 0.1,
43
+ /**
44
+ * Tag and subtag case has been normalized to canonical
45
+ * letter case (e.g. lower-case language and upper-case
46
+ * region) but no other normalization has been applied.
47
+ */
48
+ canonical: 0.9,
49
+ /**
50
+ * All tag recommendations have been applied - e.g. suppressed
51
+ * script is removed, deprecated or grandfathered values are
52
+ * replaced with preferred values.
53
+ */
54
+ preferred: 1.0
55
+ };
56
+
57
+ /**
58
+ * Determines which of two normalization ranks is most normalized.
59
+ * @param n1 - The first {@link TagNormalization} to be compared.
60
+ * @param n2 - The second {@link TagNormalization} to me compared.
61
+ * @returns `1` if `n1` is more normalized, `-1` if `n2` is more
62
+ * normalized, or `0` if they are identical.
63
+ * @public
64
+ */
65
+ export function compareNormalization(n1: TagNormalization, n2: TagNormalization): -1 | 0 | 1 {
66
+ if (normalizationRank[n1] > normalizationRank[n2]) {
67
+ return 1;
68
+ } else if (normalizationRank[n1] < normalizationRank[n2]) {
69
+ return -1;
70
+ }
71
+ return 0;
72
+ }
73
+
74
+ /**
75
+ * Chooses the most normalized of two normalization ranks.
76
+ * @param n1 - The first {@link TagNormalization} to be compared.
77
+ * @param n2 - The second {@link TagNormalization} to me compared.
78
+ * @returns The most normalized of `n1` or `n2`.
79
+ * @public
80
+ */
81
+ export function mostNormalized(n1: TagNormalization, n2: TagNormalization): TagNormalization {
82
+ /* c8 ignore next - hard to hit due to guards */
83
+ return normalizationRank[n1] > normalizationRank[n2] ? n1 : n2;
84
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright (c) 2022 Erik Fortune
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ // istanbul ignore file
23
+
24
+ export * from './common';
25
+ export { NormalizeTag } from './normalizeTag';
26
+ export { CanonicalNormalizer } from './canonicalNormalizer';
27
+ export { PreferredNormalizer } from './preferredTagNormalizer';