@budiauktioner/buildi-primitives 0.2.0 → 0.3.0

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 (144) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/PARITY.md +7 -7
  3. package/README.md +18 -1
  4. package/dist/cjs/contact/phone-number-test-data.js +1 -1
  5. package/dist/cjs/contact/phone-number-test-data.js.map +1 -1
  6. package/dist/cjs/contact/phone-number.js +36 -14
  7. package/dist/cjs/contact/phone-number.js.map +2 -2
  8. package/dist/cjs/internal/scan-boundaries.js +26 -0
  9. package/dist/cjs/internal/scan-boundaries.js.map +7 -0
  10. package/dist/cjs/measurement/area.js +2 -1
  11. package/dist/cjs/measurement/area.js.map +2 -2
  12. package/dist/cjs/measurement/data-size.js +1 -1
  13. package/dist/cjs/measurement/data-size.js.map +1 -1
  14. package/dist/cjs/measurement/electric-charge.js +1 -1
  15. package/dist/cjs/measurement/electric-charge.js.map +1 -1
  16. package/dist/cjs/measurement/electric-current.js +1 -1
  17. package/dist/cjs/measurement/electric-current.js.map +1 -1
  18. package/dist/cjs/measurement/energy.js +1 -1
  19. package/dist/cjs/measurement/energy.js.map +1 -1
  20. package/dist/cjs/measurement/flow-rate.js +1 -1
  21. package/dist/cjs/measurement/flow-rate.js.map +1 -1
  22. package/dist/cjs/measurement/frequency.js +1 -1
  23. package/dist/cjs/measurement/frequency.js.map +1 -1
  24. package/dist/cjs/measurement/length.js +1 -1
  25. package/dist/cjs/measurement/length.js.map +1 -1
  26. package/dist/cjs/measurement/luminance.js +1 -1
  27. package/dist/cjs/measurement/luminance.js.map +1 -1
  28. package/dist/cjs/measurement/luminous-flux.js +4 -1
  29. package/dist/cjs/measurement/luminous-flux.js.map +2 -2
  30. package/dist/cjs/measurement/percentage.js +1 -1
  31. package/dist/cjs/measurement/percentage.js.map +1 -1
  32. package/dist/cjs/measurement/power.js +7 -3
  33. package/dist/cjs/measurement/power.js.map +2 -2
  34. package/dist/cjs/measurement/pressure.js +1 -1
  35. package/dist/cjs/measurement/pressure.js.map +1 -1
  36. package/dist/cjs/measurement/rotational-speed.js +1 -1
  37. package/dist/cjs/measurement/rotational-speed.js.map +1 -1
  38. package/dist/cjs/measurement/sound-level.js +5 -1
  39. package/dist/cjs/measurement/sound-level.js.map +2 -2
  40. package/dist/cjs/measurement/speed.js +1 -1
  41. package/dist/cjs/measurement/speed.js.map +1 -1
  42. package/dist/cjs/measurement/temperature.js +1 -1
  43. package/dist/cjs/measurement/temperature.js.map +2 -2
  44. package/dist/cjs/measurement/torque.js +1 -1
  45. package/dist/cjs/measurement/torque.js.map +1 -1
  46. package/dist/cjs/measurement/voltage.js +1 -1
  47. package/dist/cjs/measurement/voltage.js.map +1 -1
  48. package/dist/cjs/measurement/volume.js +1 -1
  49. package/dist/cjs/measurement/volume.js.map +1 -1
  50. package/dist/cjs/measurement/weight.js +1 -1
  51. package/dist/cjs/measurement/weight.js.map +1 -1
  52. package/dist/cjs/organization/swedish-organization-number.js.map +2 -2
  53. package/dist/cjs/register-default-text-scanners.js +2 -0
  54. package/dist/cjs/register-default-text-scanners.js.map +2 -2
  55. package/dist/cjs/sample-data/index.js +18 -1
  56. package/dist/cjs/sample-data/index.js.map +2 -2
  57. package/dist/cjs/text-scanning/text-scan-result.js +3 -0
  58. package/dist/cjs/text-scanning/text-scan-result.js.map +2 -2
  59. package/dist/cjs/validation/validation-error-reason.js +6 -1
  60. package/dist/cjs/validation/validation-error-reason.js.map +2 -2
  61. package/dist/cjs/vehicle/index.js +4 -0
  62. package/dist/cjs/vehicle/index.js.map +2 -2
  63. package/dist/cjs/vehicle/watercraft-identification-number.js +332 -0
  64. package/dist/cjs/vehicle/watercraft-identification-number.js.map +7 -0
  65. package/dist/esm/contact/phone-number-test-data.js +1 -1
  66. package/dist/esm/contact/phone-number-test-data.js.map +1 -1
  67. package/dist/esm/contact/phone-number.js +36 -14
  68. package/dist/esm/contact/phone-number.js.map +2 -2
  69. package/dist/esm/internal/scan-boundaries.js +6 -0
  70. package/dist/esm/internal/scan-boundaries.js.map +7 -0
  71. package/dist/esm/measurement/area.js +2 -1
  72. package/dist/esm/measurement/area.js.map +2 -2
  73. package/dist/esm/measurement/data-size.js +1 -1
  74. package/dist/esm/measurement/data-size.js.map +1 -1
  75. package/dist/esm/measurement/electric-charge.js +1 -1
  76. package/dist/esm/measurement/electric-charge.js.map +1 -1
  77. package/dist/esm/measurement/electric-current.js +1 -1
  78. package/dist/esm/measurement/electric-current.js.map +1 -1
  79. package/dist/esm/measurement/energy.js +1 -1
  80. package/dist/esm/measurement/energy.js.map +1 -1
  81. package/dist/esm/measurement/flow-rate.js +1 -1
  82. package/dist/esm/measurement/flow-rate.js.map +1 -1
  83. package/dist/esm/measurement/frequency.js +1 -1
  84. package/dist/esm/measurement/frequency.js.map +1 -1
  85. package/dist/esm/measurement/length.js +1 -1
  86. package/dist/esm/measurement/length.js.map +1 -1
  87. package/dist/esm/measurement/luminance.js +1 -1
  88. package/dist/esm/measurement/luminance.js.map +1 -1
  89. package/dist/esm/measurement/luminous-flux.js +4 -1
  90. package/dist/esm/measurement/luminous-flux.js.map +2 -2
  91. package/dist/esm/measurement/percentage.js +1 -1
  92. package/dist/esm/measurement/percentage.js.map +1 -1
  93. package/dist/esm/measurement/power.js +7 -3
  94. package/dist/esm/measurement/power.js.map +2 -2
  95. package/dist/esm/measurement/pressure.js +1 -1
  96. package/dist/esm/measurement/pressure.js.map +1 -1
  97. package/dist/esm/measurement/rotational-speed.js +1 -1
  98. package/dist/esm/measurement/rotational-speed.js.map +1 -1
  99. package/dist/esm/measurement/sound-level.js +5 -1
  100. package/dist/esm/measurement/sound-level.js.map +2 -2
  101. package/dist/esm/measurement/speed.js +1 -1
  102. package/dist/esm/measurement/speed.js.map +1 -1
  103. package/dist/esm/measurement/temperature.js +1 -1
  104. package/dist/esm/measurement/temperature.js.map +2 -2
  105. package/dist/esm/measurement/torque.js +1 -1
  106. package/dist/esm/measurement/torque.js.map +1 -1
  107. package/dist/esm/measurement/voltage.js +1 -1
  108. package/dist/esm/measurement/voltage.js.map +1 -1
  109. package/dist/esm/measurement/volume.js +1 -1
  110. package/dist/esm/measurement/volume.js.map +1 -1
  111. package/dist/esm/measurement/weight.js +1 -1
  112. package/dist/esm/measurement/weight.js.map +1 -1
  113. package/dist/esm/organization/swedish-organization-number.js.map +2 -2
  114. package/dist/esm/register-default-text-scanners.js +2 -0
  115. package/dist/esm/register-default-text-scanners.js.map +2 -2
  116. package/dist/esm/sample-data/index.js +18 -1
  117. package/dist/esm/sample-data/index.js.map +2 -2
  118. package/dist/esm/text-scanning/text-scan-result.js +3 -0
  119. package/dist/esm/text-scanning/text-scan-result.js.map +2 -2
  120. package/dist/esm/validation/validation-error-reason.js +6 -1
  121. package/dist/esm/validation/validation-error-reason.js.map +2 -2
  122. package/dist/esm/vehicle/index.js +8 -0
  123. package/dist/esm/vehicle/index.js.map +2 -2
  124. package/dist/esm/vehicle/watercraft-identification-number.js +315 -0
  125. package/dist/esm/vehicle/watercraft-identification-number.js.map +7 -0
  126. package/dist/types/banking/index.d.cts +2 -2
  127. package/dist/types/banking/index.d.ts +2 -2
  128. package/dist/types/contact/index.d.cts +1 -1
  129. package/dist/types/contact/index.d.ts +1 -1
  130. package/dist/types/index.d.cts +2 -1
  131. package/dist/types/index.d.ts +2 -1
  132. package/dist/types/sample-data/index.d.cts +10 -2
  133. package/dist/types/sample-data/index.d.ts +10 -2
  134. package/dist/types/text-scanning/index.d.cts +3 -1
  135. package/dist/types/text-scanning/index.d.ts +3 -1
  136. package/dist/types/validation/index.d.cts +4 -0
  137. package/dist/types/validation/index.d.ts +4 -0
  138. package/dist/types/vehicle/index.d.cts +2 -0
  139. package/dist/types/vehicle/index.d.ts +2 -0
  140. package/dist/types/watercraft-identification-number-Db1I2LQM.d.cts +123 -0
  141. package/dist/types/watercraft-identification-number-o8B3C6Nx.d.ts +123 -0
  142. package/package.json +18 -13
  143. package/dist/types/{swedish-swish-number-CL6Gx_h3.d.cts → swedish-swish-number-Bh-UbVoN.d.cts} +136 -136
  144. package/dist/types/{swedish-swish-number-DDG3mNDg.d.ts → swedish-swish-number-C2Wccuyr.d.ts} +136 -136
@@ -48,6 +48,11 @@ const ValidationErrorReason = {
48
48
  // --- Email ---
49
49
  MissingAtSign: "MissingAtSign",
50
50
  InvalidLocalPart: "InvalidLocalPart",
51
- InvalidDomain: "InvalidDomain"
51
+ InvalidDomain: "InvalidDomain",
52
+ // --- Watercraft identification ---
53
+ InvalidManufacturerCode: "InvalidManufacturerCode",
54
+ InvalidSerialNumber: "InvalidSerialNumber",
55
+ InvalidMonthCode: "InvalidMonthCode",
56
+ InvalidYearDigits: "InvalidYearDigits"
52
57
  };
53
58
  //# sourceMappingURL=validation-error-reason.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/validation/validation-error-reason.ts"],
4
- "sourcesContent": ["/**\n * Describes why a value failed validation. Shared across all types that support\n * the `validate` method. Not every reason applies to every type.\n *\n * Maps 1:1 to the .NET `ValidationErrorReason` enum.\n */\nexport const ValidationErrorReason = {\n // --- Common ---\n InputIsEmpty: \"InputIsEmpty\",\n InputTooLong: \"InputTooLong\",\n InputTooShort: \"InputTooShort\",\n InvalidLength: \"InvalidLength\",\n InvalidFormat: \"InvalidFormat\",\n InvalidCharacters: \"InvalidCharacters\",\n InvalidCheckDigit: \"InvalidCheckDigit\",\n\n // --- Banking / clearing ---\n UnknownClearingRange: \"UnknownClearingRange\",\n InvalidSwedbankFormat: \"InvalidSwedbankFormat\",\n InvalidAccountLengthForBank: \"InvalidAccountLengthForBank\",\n InvalidClearingNumber: \"InvalidClearingNumber\",\n\n // --- Identity / organization ---\n InvalidDate: \"InvalidDate\",\n InvalidPrefix: \"InvalidPrefix\",\n InvalidEntityPattern: \"InvalidEntityPattern\",\n\n // --- International / country ---\n UnknownCountryCode: \"UnknownCountryCode\",\n InvalidCountryPrefix: \"InvalidCountryPrefix\",\n InvalidLengthForCountry: \"InvalidLengthForCountry\",\n\n // --- OCR ---\n InvalidLengthDigit: \"InvalidLengthDigit\",\n\n // --- Email ---\n MissingAtSign: \"MissingAtSign\",\n InvalidLocalPart: \"InvalidLocalPart\",\n InvalidDomain: \"InvalidDomain\",\n} as const;\n\nexport type ValidationErrorReason =\n (typeof ValidationErrorReason)[keyof typeof ValidationErrorReason];\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMO,MAAM,wBAAwB;AAAA;AAAA,EAEnC,cAAc;AAAA,EACd,cAAc;AAAA,EACd,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,mBAAmB;AAAA;AAAA,EAGnB,sBAAsB;AAAA,EACtB,uBAAuB;AAAA,EACvB,6BAA6B;AAAA,EAC7B,uBAAuB;AAAA;AAAA,EAGvB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,sBAAsB;AAAA;AAAA,EAGtB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA;AAAA,EAGzB,oBAAoB;AAAA;AAAA,EAGpB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,eAAe;AACjB;",
4
+ "sourcesContent": ["/**\n * Describes why a value failed validation. Shared across all types that support\n * the `validate` method. Not every reason applies to every type.\n *\n * Maps 1:1 to the .NET `ValidationErrorReason` enum.\n */\nexport const ValidationErrorReason = {\n // --- Common ---\n InputIsEmpty: \"InputIsEmpty\",\n InputTooLong: \"InputTooLong\",\n InputTooShort: \"InputTooShort\",\n InvalidLength: \"InvalidLength\",\n InvalidFormat: \"InvalidFormat\",\n InvalidCharacters: \"InvalidCharacters\",\n InvalidCheckDigit: \"InvalidCheckDigit\",\n\n // --- Banking / clearing ---\n UnknownClearingRange: \"UnknownClearingRange\",\n InvalidSwedbankFormat: \"InvalidSwedbankFormat\",\n InvalidAccountLengthForBank: \"InvalidAccountLengthForBank\",\n InvalidClearingNumber: \"InvalidClearingNumber\",\n\n // --- Identity / organization ---\n InvalidDate: \"InvalidDate\",\n InvalidPrefix: \"InvalidPrefix\",\n InvalidEntityPattern: \"InvalidEntityPattern\",\n\n // --- International / country ---\n UnknownCountryCode: \"UnknownCountryCode\",\n InvalidCountryPrefix: \"InvalidCountryPrefix\",\n InvalidLengthForCountry: \"InvalidLengthForCountry\",\n\n // --- OCR ---\n InvalidLengthDigit: \"InvalidLengthDigit\",\n\n // --- Email ---\n MissingAtSign: \"MissingAtSign\",\n InvalidLocalPart: \"InvalidLocalPart\",\n InvalidDomain: \"InvalidDomain\",\n\n // --- Watercraft identification ---\n InvalidManufacturerCode: \"InvalidManufacturerCode\",\n InvalidSerialNumber: \"InvalidSerialNumber\",\n InvalidMonthCode: \"InvalidMonthCode\",\n InvalidYearDigits: \"InvalidYearDigits\",\n} as const;\n\nexport type ValidationErrorReason =\n (typeof ValidationErrorReason)[keyof typeof ValidationErrorReason];\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMO,MAAM,wBAAwB;AAAA;AAAA,EAEnC,cAAc;AAAA,EACd,cAAc;AAAA,EACd,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,mBAAmB;AAAA;AAAA,EAGnB,sBAAsB;AAAA,EACtB,uBAAuB;AAAA,EACvB,6BAA6B;AAAA,EAC7B,uBAAuB;AAAA;AAAA,EAGvB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,sBAAsB;AAAA;AAAA,EAGtB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA;AAAA,EAGzB,oBAAoB;AAAA;AAAA,EAGpB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,eAAe;AAAA;AAAA,EAGf,yBAAyB;AAAA,EACzB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,mBAAmB;AACrB;",
6
6
  "names": []
7
7
  }
@@ -47,6 +47,8 @@ __export(vehicle_exports, {
47
47
  TrackType: () => import_track_type.TrackType,
48
48
  TransmissionType: () => import_transmission_type.TransmissionType,
49
49
  VehicleIdentificationNumber: () => import_vehicle_identification_number.VehicleIdentificationNumber,
50
+ WatercraftIdentificationNumber: () => import_watercraft_identification_number.WatercraftIdentificationNumber,
51
+ WatercraftIdentificationNumberScheme: () => import_watercraft_identification_number.WatercraftIdentificationNumberScheme,
50
52
  WheelRimDimension: () => import_wheel_rim_dimension.WheelRimDimension,
51
53
  getBiluppgifterUrl: () => import_vehicle_extensions.getBiluppgifterUrl,
52
54
  getCarInfoUrl: () => import_vehicle_extensions.getCarInfoUrl,
@@ -69,6 +71,7 @@ __export(vehicle_exports, {
69
71
  maskTireType: () => import_vehicle_masking.maskTireType,
70
72
  maskTrackType: () => import_vehicle_masking.maskTrackType,
71
73
  maskVehicleIdentificationNumber: () => import_vehicle_identification_number.maskVehicleIdentificationNumber,
74
+ maskWatercraftIdentificationNumber: () => import_watercraft_identification_number.maskWatercraftIdentificationNumber,
72
75
  maskWheelRimDimension: () => import_wheel_rim_dimension.maskWheelRimDimension,
73
76
  toBiluppgifterUrl: () => import_vehicle_extensions.toBiluppgifterUrl
74
77
  });
@@ -102,6 +105,7 @@ var import_eu_vehicle_category = require("./eu-vehicle-category.js");
102
105
  var import_swedish_vehicle_registration_number = require("./swedish-vehicle-registration-number.js");
103
106
  var import_tire_dimension = require("./tire-dimension.js");
104
107
  var import_vehicle_identification_number = require("./vehicle-identification-number.js");
108
+ var import_watercraft_identification_number = require("./watercraft-identification-number.js");
105
109
  var import_wheel_rim_dimension = require("./wheel-rim-dimension.js");
106
110
  var import_vehicle_extensions = require("./vehicle-extensions.js");
107
111
  var import_vehicle_masking = require("./vehicle-masking.js");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/vehicle/index.ts"],
4
- "sourcesContent": ["export {\n BoatCeDesignCategory,\n type BoatCeDesignCategoryFormatOptions,\n} from \"./boat-ce-design-category.js\";\nexport { BoatHullMaterial, type BoatHullMaterialFormatOptions } from \"./boat-hull-material.js\";\nexport { BodyType, type BodyTypeFormatOptions } from \"./body-type.js\";\nexport { DrivetrainType, type DrivetrainTypeFormatOptions } from \"./drivetrain-type.js\";\nexport { EuroEmissionClass, type EuroEmissionClassFormatOptions } from \"./euro-emission-class.js\";\nexport {\n FuelConsumptionNorm,\n type FuelConsumptionNormFormatOptions,\n} from \"./fuel-consumption-norm.js\";\nexport { FuelType, type FuelTypeFormatOptions } from \"./fuel-type.js\";\nexport { SuspensionType, type SuspensionTypeFormatOptions } from \"./suspension-type.js\";\nexport {\n SwedishDrivingLicenseCategory,\n type SwedishDrivingLicenseCategoryFormatOptions,\n} from \"./swedish-driving-license-category.js\";\nexport { SwedishDrivingLicenseVehicleGroup } from \"./swedish-driving-license-vehicle-group.js\";\nexport {\n SwedishEcoVehicleClassification,\n type SwedishEcoVehicleClassificationFormatOptions,\n} from \"./swedish-eco-vehicle-classification.js\";\nexport {\n SwedishVehicleStatus,\n type SwedishVehicleStatusFormatOptions,\n} from \"./swedish-vehicle-status.js\";\nexport {\n SwedishVehicleType,\n type SwedishVehicleTypeFormatOptions,\n} from \"./swedish-vehicle-type.js\";\nexport { TireType, type TireTypeFormatOptions } from \"./tire-type.js\";\nexport { TrackType, type TrackTypeFormatOptions } from \"./track-type.js\";\nexport { TransmissionType, type TransmissionTypeFormatOptions } from \"./transmission-type.js\";\n\nexport { EmissionRate, maskEmissionRate, type EmissionRateFormatOptions } from \"./emission-rate.js\";\nexport {\n EnergyConsumption,\n maskEnergyConsumption,\n type EnergyConsumptionFormatOptions,\n} from \"./energy-consumption.js\";\nexport { EngineDisplacement, type EngineDisplacementFormatOptions } from \"./engine-displacement.js\";\nexport { EnginePower, maskEnginePower, type EnginePowerFormatOptions } from \"./engine-power.js\";\nexport {\n FuelConsumption,\n maskFuelConsumption,\n type FuelConsumptionFormatOptions,\n} from \"./fuel-consumption.js\";\nexport { OdometerReading, type OdometerReadingFormatOptions } from \"./odometer-reading.js\";\nexport {\n OperatingHours,\n maskOperatingHours,\n type OperatingHoursFormatOptions,\n} from \"./operating-hours.js\";\n\nexport { BoltPattern, maskBoltPattern, type BoltPatternFormatOptions } from \"./bolt-pattern.js\";\nexport {\n EuTypeApprovalNumber,\n maskEuTypeApprovalNumber,\n type EuTypeApprovalNumberFormatOptions,\n} from \"./eu-type-approval-number.js\";\nexport { EuVehicleCategory, type EuVehicleCategoryFormatOptions } from \"./eu-vehicle-category.js\";\nexport {\n SwedishVehicleRegistrationNumber,\n maskSwedishVehicleRegistrationNumber,\n type SwedishVehicleRegistrationNumberFormatOptions,\n} from \"./swedish-vehicle-registration-number.js\";\nexport {\n TireDimension,\n maskTireDimension,\n type TireDimensionFormatOptions,\n} from \"./tire-dimension.js\";\nexport {\n VehicleIdentificationNumber,\n maskVehicleIdentificationNumber,\n type VehicleIdentificationNumberFormatOptions,\n} from \"./vehicle-identification-number.js\";\nexport {\n WheelRimDimension,\n maskWheelRimDimension,\n type WheelRimDimensionFormatOptions,\n} from \"./wheel-rim-dimension.js\";\n\nexport { getBiluppgifterUrl, getCarInfoUrl, toBiluppgifterUrl } from \"./vehicle-extensions.js\";\n\nexport {\n maskBoatCeDesignCategory,\n maskBoatHullMaterial,\n maskBodyType,\n maskDrivetrainType,\n maskFuelConsumptionNorm,\n maskSuspensionType,\n maskSwedishEcoVehicleClassification,\n maskTireType,\n maskTrackType,\n} from \"./vehicle-masking.js\";\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qCAGO;AACP,gCAAqE;AACrE,uBAAqD;AACrD,6BAAiE;AACjE,iCAAuE;AACvE,mCAGO;AACP,uBAAqD;AACrD,6BAAiE;AACjE,8CAGO;AACP,mDAAkD;AAClD,gDAGO;AACP,oCAGO;AACP,kCAGO;AACP,uBAAqD;AACrD,wBAAuD;AACvD,+BAAqE;AAErE,2BAA+E;AAC/E,gCAIO;AACP,iCAAyE;AACzE,0BAA4E;AAC5E,8BAIO;AACP,8BAAmE;AACnE,6BAIO;AAEP,0BAA4E;AAC5E,qCAIO;AACP,iCAAuE;AACvE,iDAIO;AACP,4BAIO;AACP,2CAIO;AACP,iCAIO;AAEP,gCAAqE;AAErE,6BAUO;",
4
+ "sourcesContent": ["export {\n BoatCeDesignCategory,\n type BoatCeDesignCategoryFormatOptions,\n} from \"./boat-ce-design-category.js\";\nexport { BoatHullMaterial, type BoatHullMaterialFormatOptions } from \"./boat-hull-material.js\";\nexport { BodyType, type BodyTypeFormatOptions } from \"./body-type.js\";\nexport { DrivetrainType, type DrivetrainTypeFormatOptions } from \"./drivetrain-type.js\";\nexport { EuroEmissionClass, type EuroEmissionClassFormatOptions } from \"./euro-emission-class.js\";\nexport {\n FuelConsumptionNorm,\n type FuelConsumptionNormFormatOptions,\n} from \"./fuel-consumption-norm.js\";\nexport { FuelType, type FuelTypeFormatOptions } from \"./fuel-type.js\";\nexport { SuspensionType, type SuspensionTypeFormatOptions } from \"./suspension-type.js\";\nexport {\n SwedishDrivingLicenseCategory,\n type SwedishDrivingLicenseCategoryFormatOptions,\n} from \"./swedish-driving-license-category.js\";\nexport { SwedishDrivingLicenseVehicleGroup } from \"./swedish-driving-license-vehicle-group.js\";\nexport {\n SwedishEcoVehicleClassification,\n type SwedishEcoVehicleClassificationFormatOptions,\n} from \"./swedish-eco-vehicle-classification.js\";\nexport {\n SwedishVehicleStatus,\n type SwedishVehicleStatusFormatOptions,\n} from \"./swedish-vehicle-status.js\";\nexport {\n SwedishVehicleType,\n type SwedishVehicleTypeFormatOptions,\n} from \"./swedish-vehicle-type.js\";\nexport { TireType, type TireTypeFormatOptions } from \"./tire-type.js\";\nexport { TrackType, type TrackTypeFormatOptions } from \"./track-type.js\";\nexport { TransmissionType, type TransmissionTypeFormatOptions } from \"./transmission-type.js\";\n\nexport { EmissionRate, maskEmissionRate, type EmissionRateFormatOptions } from \"./emission-rate.js\";\nexport {\n EnergyConsumption,\n maskEnergyConsumption,\n type EnergyConsumptionFormatOptions,\n} from \"./energy-consumption.js\";\nexport { EngineDisplacement, type EngineDisplacementFormatOptions } from \"./engine-displacement.js\";\nexport { EnginePower, maskEnginePower, type EnginePowerFormatOptions } from \"./engine-power.js\";\nexport {\n FuelConsumption,\n maskFuelConsumption,\n type FuelConsumptionFormatOptions,\n} from \"./fuel-consumption.js\";\nexport { OdometerReading, type OdometerReadingFormatOptions } from \"./odometer-reading.js\";\nexport {\n OperatingHours,\n maskOperatingHours,\n type OperatingHoursFormatOptions,\n} from \"./operating-hours.js\";\n\nexport { BoltPattern, maskBoltPattern, type BoltPatternFormatOptions } from \"./bolt-pattern.js\";\nexport {\n EuTypeApprovalNumber,\n maskEuTypeApprovalNumber,\n type EuTypeApprovalNumberFormatOptions,\n} from \"./eu-type-approval-number.js\";\nexport { EuVehicleCategory, type EuVehicleCategoryFormatOptions } from \"./eu-vehicle-category.js\";\nexport {\n SwedishVehicleRegistrationNumber,\n maskSwedishVehicleRegistrationNumber,\n type SwedishVehicleRegistrationNumberFormatOptions,\n} from \"./swedish-vehicle-registration-number.js\";\nexport {\n TireDimension,\n maskTireDimension,\n type TireDimensionFormatOptions,\n} from \"./tire-dimension.js\";\nexport {\n VehicleIdentificationNumber,\n maskVehicleIdentificationNumber,\n type VehicleIdentificationNumberFormatOptions,\n} from \"./vehicle-identification-number.js\";\nexport {\n WatercraftIdentificationNumber,\n WatercraftIdentificationNumberScheme,\n maskWatercraftIdentificationNumber,\n type WatercraftIdentificationNumberFormatOptions,\n} from \"./watercraft-identification-number.js\";\nexport {\n WheelRimDimension,\n maskWheelRimDimension,\n type WheelRimDimensionFormatOptions,\n} from \"./wheel-rim-dimension.js\";\n\nexport { getBiluppgifterUrl, getCarInfoUrl, toBiluppgifterUrl } from \"./vehicle-extensions.js\";\n\nexport {\n maskBoatCeDesignCategory,\n maskBoatHullMaterial,\n maskBodyType,\n maskDrivetrainType,\n maskFuelConsumptionNorm,\n maskSuspensionType,\n maskSwedishEcoVehicleClassification,\n maskTireType,\n maskTrackType,\n} from \"./vehicle-masking.js\";\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qCAGO;AACP,gCAAqE;AACrE,uBAAqD;AACrD,6BAAiE;AACjE,iCAAuE;AACvE,mCAGO;AACP,uBAAqD;AACrD,6BAAiE;AACjE,8CAGO;AACP,mDAAkD;AAClD,gDAGO;AACP,oCAGO;AACP,kCAGO;AACP,uBAAqD;AACrD,wBAAuD;AACvD,+BAAqE;AAErE,2BAA+E;AAC/E,gCAIO;AACP,iCAAyE;AACzE,0BAA4E;AAC5E,8BAIO;AACP,8BAAmE;AACnE,6BAIO;AAEP,0BAA4E;AAC5E,qCAIO;AACP,iCAAuE;AACvE,iDAIO;AACP,4BAIO;AACP,2CAIO;AACP,8CAKO;AACP,iCAIO;AAEP,gCAAqE;AAErE,6BAUO;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,332 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var watercraft_identification_number_exports = {};
20
+ __export(watercraft_identification_number_exports, {
21
+ WatercraftIdentificationNumber: () => WatercraftIdentificationNumber,
22
+ WatercraftIdentificationNumberScheme: () => WatercraftIdentificationNumberScheme,
23
+ maskWatercraftIdentificationNumber: () => maskWatercraftIdentificationNumber
24
+ });
25
+ module.exports = __toCommonJS(watercraft_identification_number_exports);
26
+ var import_country = require("../geography/country.js");
27
+ var import_input_sanitization = require("../internal/input-sanitization.js");
28
+ var import_text_candidate = require("../text-scanning/text-candidate.js");
29
+ var import_text_candidate_category = require("../text-scanning/text-candidate-category.js");
30
+ var import_text_match_confidence = require("../text-scanning/text-match-confidence.js");
31
+ var import_validation_error_reason = require("../validation/validation-error-reason.js");
32
+ var import_validation_issue = require("../validation/validation-issue.js");
33
+ var import_validation_result = require("../validation/validation-result.js");
34
+ const WatercraftIdentificationNumberScheme = {
35
+ Unknown: 0,
36
+ /**
37
+ * ISO 10087 craft or watercraft identification number (CIN/WIN): a two-letter
38
+ * country code, a hyphen and twelve characters, e.g. `NL-HXAB7A33G506`.
39
+ */
40
+ Iso10087: 1,
41
+ /**
42
+ * United States hull identification number (HIN) in the twelve-character format
43
+ * required since 1 August 1984 by 33 CFR 181.25, e.g. `ZZZ00001A020`.
44
+ */
45
+ UnitedStatesHullIdentificationNumber: 2
46
+ };
47
+ const MAX_INPUT_LENGTH = 30;
48
+ const ISO_LENGTH = 14;
49
+ const UNITED_STATES_LENGTH = 12;
50
+ const ALLOWED_CHARACTERS_PATTERN = /^[A-Z0-9-]+$/u;
51
+ const WHITESPACE_PATTERN = / +/g;
52
+ const LOWERCASE_ASCII_PATTERN = /[a-z]/g;
53
+ const DOTNET_WHITESPACE_ONLY_PATTERN = /^[\p{Z}\t\n\v\f\r\u0085]*$/u;
54
+ const DOTNET_TRIM_PATTERN = /^[\p{Z}\t\n\v\f\r\u0085]+|[\p{Z}\t\n\v\f\r\u0085]+$/gu;
55
+ const COUNTRY_CODE_PATTERN = /^[A-Z]{2}$/u;
56
+ const ISO_MANUFACTURER_CODE_PATTERN = /^[A-Z2-9]{3}$/u;
57
+ const UNITED_STATES_MANUFACTURER_CODE_PATTERN = /^[A-Z0-9]{3}$/u;
58
+ const SERIAL_NUMBER_PATTERN = /^[A-HJ-NPR-Z0-9]{5}$/u;
59
+ const YEAR_DIGITS_PATTERN = /^[0-9]{3}$/u;
60
+ const SCAN_PATTERN = /(?<![A-Z0-9-])(?:[A-Z]{2}-?[A-Z0-9]{12}|[A-Z0-9]{12})(?![A-Z0-9-])/gu;
61
+ class WatercraftIdentificationNumber {
62
+ static typeInfo = Object.freeze({
63
+ englishName: "Watercraft Identification Number",
64
+ localizedName: "Skrovnummer",
65
+ emoji: "\u{1F6A4}",
66
+ sources: Object.freeze([
67
+ "https://www.iso.org/standard/82383.html",
68
+ "https://www.ecfr.gov/current/title-33/chapter-I/subchapter-S/part-181/subpart-C/section-181.25",
69
+ "https://www.transportstyrelsen.se/sv/sjofart/fritidsbatar/lagar-och-regler-for-fritidsbatar/cemarkning/bygga-om-tillverka-distribuera-och-importera/tillverka/instruktionsbok-tillverkarskylt-och-win/"
70
+ ])
71
+ });
72
+ /**
73
+ * The number in uppercase without separators: fourteen characters for ISO 10087,
74
+ * e.g. `NLHXAB7A33G506`, or twelve for a US HIN, e.g. `ZZZ00001A020`.
75
+ */
76
+ value;
77
+ /**
78
+ * The number as it is marked on the hull: ISO 10087 with the hyphen after the
79
+ * country code, e.g. `NL-HXAB7A33G506`, and a US HIN unchanged, e.g. `ZZZ00001A020`.
80
+ */
81
+ formatted;
82
+ /** Which of the two supported formats the number follows. */
83
+ scheme;
84
+ /**
85
+ * The ISO 3166-1 alpha-2 code of the country where the manufacturer is established,
86
+ * e.g. `NL`, or `null` for a US HIN, which carries no country.
87
+ */
88
+ countryCode;
89
+ /** The country of {@link countryCode}, or `null` for a US HIN. */
90
+ country;
91
+ /** The three-character manufacturer identification code (MIC), e.g. `HXA`. */
92
+ manufacturerCode;
93
+ /** The five-character serial number assigned by the manufacturer, e.g. `B7A33`. */
94
+ serialNumber;
95
+ /**
96
+ * The production month letter, `A` for January through `L` for December. For a US
97
+ * HIN this is the month of certification when one is required, otherwise the month
98
+ * of manufacture.
99
+ */
100
+ productionMonthCode;
101
+ /** The production month decoded from {@link productionMonthCode}, 1–12. */
102
+ productionMonth;
103
+ /** The last digit of the production year, 0–9. The decade is not encoded. */
104
+ productionYearDigit;
105
+ /** The last two digits of the model year as written, e.g. `06`. The century is not encoded. */
106
+ modelYearDigits;
107
+ constructor(value, scheme, country) {
108
+ this.value = value;
109
+ this.scheme = scheme;
110
+ this.country = country;
111
+ const isIso = scheme === WatercraftIdentificationNumberScheme.Iso10087;
112
+ const body = isIso ? value.slice(2) : value;
113
+ this.countryCode = isIso ? value.slice(0, 2) : null;
114
+ this.formatted = this.countryCode === null ? value : `${this.countryCode}-${body}`;
115
+ this.manufacturerCode = body.slice(0, 3);
116
+ this.serialNumber = body.slice(3, 8);
117
+ this.productionMonthCode = body[8];
118
+ this.productionMonth = body.charCodeAt(8) - 64;
119
+ this.productionYearDigit = body.charCodeAt(9) - 48;
120
+ this.modelYearDigits = body.slice(10, 12);
121
+ }
122
+ static tryParse(input) {
123
+ return WatercraftIdentificationNumber.tryParseCore(input, null);
124
+ }
125
+ static parse(input) {
126
+ const result = WatercraftIdentificationNumber.tryParse(input);
127
+ if (result === null) throw new Error("Invalid watercraft identification number.");
128
+ return result;
129
+ }
130
+ static isValid(input) {
131
+ return WatercraftIdentificationNumber.tryParse(input) !== null;
132
+ }
133
+ /**
134
+ * Returns the number as it is marked on the hull, e.g. `NL-HXAB7A33G506` or
135
+ * `ZZZ00001A020`.
136
+ */
137
+ static format(input, options) {
138
+ const parsed = WatercraftIdentificationNumber.tryParse(input);
139
+ if (parsed !== null) return parsed.formatted;
140
+ return fallback(input, options);
141
+ }
142
+ /**
143
+ * Returns the number in uppercase without separators, e.g. `NLHXAB7A33G506` or
144
+ * `ZZZ00001A020`.
145
+ */
146
+ static normalize(input, options) {
147
+ const parsed = WatercraftIdentificationNumber.tryParse(input);
148
+ if (parsed !== null) return parsed.value;
149
+ return fallback(input, options);
150
+ }
151
+ static isNormalized(input) {
152
+ return input != null && WatercraftIdentificationNumber.normalize(input) === input;
153
+ }
154
+ /**
155
+ * Describes every invalid segment of the input, one issue per segment, or reports
156
+ * it as valid.
157
+ */
158
+ static validate(input) {
159
+ const issues = [];
160
+ return WatercraftIdentificationNumber.tryParseCore(input, issues) !== null ? (0, import_validation_result.validResult)(input) : (0, import_validation_result.invalidResult)(input, issues);
161
+ }
162
+ /**
163
+ * Finds watercraft identification number candidates in unstructured text. An ISO
164
+ * 10087 number written with its hyphen is reported with medium confidence; one
165
+ * without the hyphen, and a US HIN, are bare runs of letters and digits and
166
+ * reported with low confidence. Results are heuristic and may include false
167
+ * positives.
168
+ */
169
+ static findCandidatesInText(text) {
170
+ if (!text) return [];
171
+ const upper = toAsciiUpper(text);
172
+ const out = [];
173
+ const pattern = new RegExp(SCAN_PATTERN.source, SCAN_PATTERN.flags);
174
+ let match;
175
+ while ((match = pattern.exec(upper)) !== null) {
176
+ const value = WatercraftIdentificationNumber.tryParse(match[0]);
177
+ if (value === null) continue;
178
+ out.push(
179
+ new import_text_candidate.TextCandidate({
180
+ startIndex: match.index,
181
+ length: match[0].length,
182
+ originalText: text.slice(match.index, match.index + match[0].length),
183
+ typeName: "WatercraftIdentificationNumber",
184
+ category: import_text_candidate_category.TextCandidateCategory.Vehicle,
185
+ normalizedForm: value.toNormalizedString(),
186
+ formattedForm: value.toString(),
187
+ maskedForm: maskWatercraftIdentificationNumber(value),
188
+ confidence: match[0].includes("-") ? import_text_match_confidence.TextMatchConfidence.Medium : import_text_match_confidence.TextMatchConfidence.Low,
189
+ value
190
+ })
191
+ );
192
+ }
193
+ return out;
194
+ }
195
+ /** Returns the number without separators, e.g. `NLHXAB7A33G506`. */
196
+ toNormalizedString() {
197
+ return this.value;
198
+ }
199
+ /** Returns the number as it is marked on the hull, e.g. `NL-HXAB7A33G506`. */
200
+ toString() {
201
+ return this.formatted;
202
+ }
203
+ equals(other) {
204
+ return other != null && this.value === other.value;
205
+ }
206
+ compareTo(other) {
207
+ if (other == null) return 1;
208
+ return this.value < other.value ? -1 : this.value > other.value ? 1 : 0;
209
+ }
210
+ static tryParseCore(input, issues) {
211
+ const fail = (reason, english, swedish) => {
212
+ issues?.push(new import_validation_issue.ValidationIssue(reason, english, swedish));
213
+ return false;
214
+ };
215
+ if (isNullOrWhiteSpace(input)) {
216
+ fail(import_validation_error_reason.ValidationErrorReason.InputIsEmpty, "Input is empty or whitespace.", "V\xE4rdet \xE4r tomt.");
217
+ return null;
218
+ }
219
+ const cleaned = toAsciiUpper((0, import_input_sanitization.sanitizeInput)(input).replace(WHITESPACE_PATTERN, ""));
220
+ if (cleaned.length > MAX_INPUT_LENGTH) {
221
+ fail(
222
+ import_validation_error_reason.ValidationErrorReason.InputTooLong,
223
+ "Input contains too many characters.",
224
+ "V\xE4rdet inneh\xE5ller f\xF6r m\xE5nga tecken."
225
+ );
226
+ return null;
227
+ }
228
+ if (!ALLOWED_CHARACTERS_PATTERN.test(cleaned)) {
229
+ fail(
230
+ import_validation_error_reason.ValidationErrorReason.InvalidCharacters,
231
+ "Only letters A\u2013Z, digits and the hyphen after the country code are allowed.",
232
+ "Endast bokst\xE4verna A\u2013Z, siffror och bindestrecket efter landskoden \xE4r till\xE5tna."
233
+ );
234
+ return null;
235
+ }
236
+ const hyphenIndex = cleaned.indexOf("-");
237
+ const hasCountrySeparator = hyphenIndex >= 0;
238
+ if (hasCountrySeparator && (hyphenIndex !== 2 || cleaned.indexOf("-", hyphenIndex + 1) >= 0)) {
239
+ fail(
240
+ import_validation_error_reason.ValidationErrorReason.InvalidFormat,
241
+ "A hyphen is only allowed directly after the two-letter country code.",
242
+ "Bindestreck f\xE5r bara st\xE5 direkt efter den tv\xE5bokstaviga landskoden."
243
+ );
244
+ return null;
245
+ }
246
+ const compact = hasCountrySeparator ? cleaned.slice(0, hyphenIndex) + cleaned.slice(hyphenIndex + 1) : cleaned;
247
+ const scheme = compact.length === ISO_LENGTH ? WatercraftIdentificationNumberScheme.Iso10087 : compact.length === UNITED_STATES_LENGTH && !hasCountrySeparator ? WatercraftIdentificationNumberScheme.UnitedStatesHullIdentificationNumber : WatercraftIdentificationNumberScheme.Unknown;
248
+ if (scheme === WatercraftIdentificationNumberScheme.Unknown) {
249
+ fail(
250
+ import_validation_error_reason.ValidationErrorReason.InvalidLength,
251
+ "Must be 14 characters after an ISO 10087 country code and hyphen, or 12 characters for a US HIN.",
252
+ "M\xE5ste vara 14 tecken enligt ISO 10087 (landskod, bindestreck och 12 tecken) eller 12 tecken f\xF6r ett amerikanskt HIN."
253
+ );
254
+ return null;
255
+ }
256
+ const isIso = scheme === WatercraftIdentificationNumberScheme.Iso10087;
257
+ const body = isIso ? compact.slice(2) : compact;
258
+ let isValid = true;
259
+ let country = null;
260
+ if (isIso) {
261
+ country = resolveCountry(compact.slice(0, 2));
262
+ if (country === null) {
263
+ isValid = fail(
264
+ import_validation_error_reason.ValidationErrorReason.UnknownCountryCode,
265
+ "The first two characters must be an ISO 3166-1 alpha-2 country code.",
266
+ "De tv\xE5 f\xF6rsta tecknen m\xE5ste vara en landskod enligt ISO 3166-1 alpha-2."
267
+ );
268
+ }
269
+ }
270
+ if (isIso && !ISO_MANUFACTURER_CODE_PATTERN.test(body.slice(0, 3))) {
271
+ isValid = fail(
272
+ import_validation_error_reason.ValidationErrorReason.InvalidManufacturerCode,
273
+ "The manufacturer code must be three letters or digits, except the digits 0 and 1.",
274
+ "Tillverkarkoden m\xE5ste vara tre bokst\xE4ver eller siffror, men inte siffrorna 0 och 1."
275
+ );
276
+ }
277
+ if (!isIso && !UNITED_STATES_MANUFACTURER_CODE_PATTERN.test(body.slice(0, 3))) {
278
+ isValid = fail(
279
+ import_validation_error_reason.ValidationErrorReason.InvalidManufacturerCode,
280
+ "The manufacturer code must be three letters or digits.",
281
+ "Tillverkarkoden m\xE5ste vara tre bokst\xE4ver eller siffror."
282
+ );
283
+ }
284
+ if (!SERIAL_NUMBER_PATTERN.test(body.slice(3, 8))) {
285
+ isValid = fail(
286
+ import_validation_error_reason.ValidationErrorReason.InvalidSerialNumber,
287
+ "The serial number must be five letters or digits, except the letters I, O and Q.",
288
+ "Serienumret m\xE5ste vara fem bokst\xE4ver eller siffror, men inte bokst\xE4verna I, O och Q."
289
+ );
290
+ }
291
+ const monthCode = body[8];
292
+ if (monthCode < "A" || monthCode > "L") {
293
+ isValid = fail(
294
+ import_validation_error_reason.ValidationErrorReason.InvalidMonthCode,
295
+ "The production month must be a letter from A (January) to L (December).",
296
+ "Tillverkningsm\xE5naden m\xE5ste vara en bokstav fr\xE5n A (januari) till L (december)."
297
+ );
298
+ }
299
+ if (!YEAR_DIGITS_PATTERN.test(body.slice(9, 12))) {
300
+ isValid = fail(
301
+ import_validation_error_reason.ValidationErrorReason.InvalidYearDigits,
302
+ "The production year and model year must be digits.",
303
+ "Tillverknings\xE5r och \xE5rsmodell m\xE5ste anges med siffror."
304
+ );
305
+ }
306
+ if (!isValid) return null;
307
+ return new WatercraftIdentificationNumber(compact, scheme, country);
308
+ }
309
+ }
310
+ function maskWatercraftIdentificationNumber(win) {
311
+ const prefix = win.countryCode === null ? win.manufacturerCode : `${win.countryCode}-${win.manufacturerCode}`;
312
+ return prefix + "*".repeat(win.formatted.length - prefix.length);
313
+ }
314
+ function resolveCountry(code) {
315
+ if (!COUNTRY_CODE_PATTERN.test(code)) return null;
316
+ const parsed = import_country.Country.tryParse(code);
317
+ return parsed !== null && parsed.alpha2Code === code ? parsed : null;
318
+ }
319
+ function toAsciiUpper(text) {
320
+ return text.replace(LOWERCASE_ASCII_PATTERN, (c) => String.fromCharCode(c.charCodeAt(0) - 32));
321
+ }
322
+ function fallback(input, options) {
323
+ if (options?.fallbackToTrimmedInputWhenInvalid !== true || isNullOrWhiteSpace(input)) return null;
324
+ return trimLikeDotnet(input);
325
+ }
326
+ function isNullOrWhiteSpace(input) {
327
+ return input == null || DOTNET_WHITESPACE_ONLY_PATTERN.test(input);
328
+ }
329
+ function trimLikeDotnet(input) {
330
+ return input.replace(DOTNET_TRIM_PATTERN, "");
331
+ }
332
+ //# sourceMappingURL=watercraft-identification-number.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/vehicle/watercraft-identification-number.ts"],
4
+ "sourcesContent": ["import { Country } from \"../geography/country.js\";\nimport { sanitizeInput } from \"../internal/input-sanitization.js\";\nimport type { PrimitiveTypeInfo } from \"../primitive-type-info.js\";\nimport { TextCandidate } from \"../text-scanning/text-candidate.js\";\nimport { TextCandidateCategory } from \"../text-scanning/text-candidate-category.js\";\nimport { TextMatchConfidence } from \"../text-scanning/text-match-confidence.js\";\nimport { ValidationErrorReason } from \"../validation/validation-error-reason.js\";\nimport { ValidationIssue } from \"../validation/validation-issue.js\";\nimport {\n invalidResult,\n validResult,\n type ValidationResult,\n} from \"../validation/validation-result.js\";\n\n/** Options for {@link WatercraftIdentificationNumber.format} and `normalize`. */\nexport interface WatercraftIdentificationNumberFormatOptions {\n fallbackToTrimmedInputWhenInvalid?: boolean;\n}\n\n/** The scheme a {@link WatercraftIdentificationNumber} was written in. */\nexport const WatercraftIdentificationNumberScheme = {\n Unknown: 0,\n /**\n * ISO 10087 craft or watercraft identification number (CIN/WIN): a two-letter\n * country code, a hyphen and twelve characters, e.g. `NL-HXAB7A33G506`.\n */\n Iso10087: 1,\n /**\n * United States hull identification number (HIN) in the twelve-character format\n * required since 1 August 1984 by 33 CFR 181.25, e.g. `ZZZ00001A020`.\n */\n UnitedStatesHullIdentificationNumber: 2,\n} as const;\n\nexport type WatercraftIdentificationNumberScheme =\n (typeof WatercraftIdentificationNumberScheme)[keyof typeof WatercraftIdentificationNumberScheme];\n\nconst MAX_INPUT_LENGTH = 30;\nconst ISO_LENGTH = 14;\nconst UNITED_STATES_LENGTH = 12;\n\nconst ALLOWED_CHARACTERS_PATTERN = /^[A-Z0-9-]+$/u;\n// sanitizeInput has already turned every whitespace character into an ASCII space and dropped\n// U+0085, U+FEFF, \\v and \\f, so a space is all that is left to strip. `\\s` would differ from the\n// .NET port, where it also matches U+0085 but not U+FEFF.\nconst WHITESPACE_PATTERN = / +/g;\nconst LOWERCASE_ASCII_PATTERN = /[a-z]/g;\nconst DOTNET_WHITESPACE_ONLY_PATTERN = /^[\\p{Z}\\t\\n\\v\\f\\r\\u0085]*$/u;\nconst DOTNET_TRIM_PATTERN = /^[\\p{Z}\\t\\n\\v\\f\\r\\u0085]+|[\\p{Z}\\t\\n\\v\\f\\r\\u0085]+$/gu;\nconst COUNTRY_CODE_PATTERN = /^[A-Z]{2}$/u;\n\n// ISO 10087 \u00A74.3: letters and numerals, except the numerals 0 and 1.\nconst ISO_MANUFACTURER_CODE_PATTERN = /^[A-Z2-9]{3}$/u;\n\n// 33 CFR 181.25(a) leaves the characters of a Coast Guard assigned code unrestricted.\nconst UNITED_STATES_MANUFACTURER_CODE_PATTERN = /^[A-Z0-9]{3}$/u;\n\n// ISO 10087 \u00A74.4 and 33 CFR 181.25(b): letters and numerals, except the letters I, O and Q.\nconst SERIAL_NUMBER_PATTERN = /^[A-HJ-NPR-Z0-9]{5}$/u;\n\nconst YEAR_DIGITS_PATTERN = /^[0-9]{3}$/u;\n\nconst SCAN_PATTERN = /(?<![A-Z0-9-])(?:[A-Z]{2}-?[A-Z0-9]{12}|[A-Z0-9]{12})(?![A-Z0-9-])/gu;\n\n/**\n * A watercraft identification number (`skrovnummer`), the hull marking of a small\n * craft: either the ISO 10087 craft identification number (CIN, now called WIN by\n * Transportstyrelsen) of fourteen characters plus a hyphen, or the twelve-character\n * US hull identification number (HIN).\n *\n * The number is assigned by the manufacturer and carries no check digit, so a parsed\n * value is structurally valid only \u2014 it does not prove that the manufacturer code is\n * registered or that the number belongs to a particular craft. The production year\n * and model year are encoded as one and two digits respectively, so the century\n * cannot be derived from the number alone; they are exposed as digits rather than\n * full years. Older markings that predate these formats (for example US HINs from\n * before August 1984) are not accepted.\n *\n * Sources:\n * - https://www.iso.org/standard/82383.html\n * - https://www.ecfr.gov/current/title-33/chapter-I/subchapter-S/part-181/subpart-C/section-181.25\n * - https://www.transportstyrelsen.se/sv/sjofart/fritidsbatar/lagar-och-regler-for-fritidsbatar/cemarkning/bygga-om-tillverka-distribuera-och-importera/tillverka/instruktionsbok-tillverkarskylt-och-win/\n */\nexport class WatercraftIdentificationNumber {\n static readonly typeInfo: PrimitiveTypeInfo = Object.freeze({\n englishName: \"Watercraft Identification Number\",\n localizedName: \"Skrovnummer\",\n emoji: \"\uD83D\uDEA4\",\n sources: Object.freeze([\n \"https://www.iso.org/standard/82383.html\",\n \"https://www.ecfr.gov/current/title-33/chapter-I/subchapter-S/part-181/subpart-C/section-181.25\",\n \"https://www.transportstyrelsen.se/sv/sjofart/fritidsbatar/lagar-och-regler-for-fritidsbatar/cemarkning/bygga-om-tillverka-distribuera-och-importera/tillverka/instruktionsbok-tillverkarskylt-och-win/\",\n ]),\n });\n\n /**\n * The number in uppercase without separators: fourteen characters for ISO 10087,\n * e.g. `NLHXAB7A33G506`, or twelve for a US HIN, e.g. `ZZZ00001A020`.\n */\n readonly value: string;\n\n /**\n * The number as it is marked on the hull: ISO 10087 with the hyphen after the\n * country code, e.g. `NL-HXAB7A33G506`, and a US HIN unchanged, e.g. `ZZZ00001A020`.\n */\n readonly formatted: string;\n\n /** Which of the two supported formats the number follows. */\n readonly scheme: WatercraftIdentificationNumberScheme;\n\n /**\n * The ISO 3166-1 alpha-2 code of the country where the manufacturer is established,\n * e.g. `NL`, or `null` for a US HIN, which carries no country.\n */\n readonly countryCode: string | null;\n\n /** The country of {@link countryCode}, or `null` for a US HIN. */\n readonly country: Country | null;\n\n /** The three-character manufacturer identification code (MIC), e.g. `HXA`. */\n readonly manufacturerCode: string;\n\n /** The five-character serial number assigned by the manufacturer, e.g. `B7A33`. */\n readonly serialNumber: string;\n\n /**\n * The production month letter, `A` for January through `L` for December. For a US\n * HIN this is the month of certification when one is required, otherwise the month\n * of manufacture.\n */\n readonly productionMonthCode: string;\n\n /** The production month decoded from {@link productionMonthCode}, 1\u201312. */\n readonly productionMonth: number;\n\n /** The last digit of the production year, 0\u20139. The decade is not encoded. */\n readonly productionYearDigit: number;\n\n /** The last two digits of the model year as written, e.g. `06`. The century is not encoded. */\n readonly modelYearDigits: string;\n\n private constructor(\n value: string,\n scheme: WatercraftIdentificationNumberScheme,\n country: Country | null,\n ) {\n this.value = value;\n this.scheme = scheme;\n this.country = country;\n\n const isIso = scheme === WatercraftIdentificationNumberScheme.Iso10087;\n const body = isIso ? value.slice(2) : value;\n this.countryCode = isIso ? value.slice(0, 2) : null;\n this.formatted = this.countryCode === null ? value : `${this.countryCode}-${body}`;\n this.manufacturerCode = body.slice(0, 3);\n this.serialNumber = body.slice(3, 8);\n this.productionMonthCode = body[8]!;\n this.productionMonth = body.charCodeAt(8) - 64;\n this.productionYearDigit = body.charCodeAt(9) - 48;\n this.modelYearDigits = body.slice(10, 12);\n }\n\n static tryParse(input: string | null | undefined): WatercraftIdentificationNumber | null {\n return WatercraftIdentificationNumber.tryParseCore(input, null);\n }\n\n static parse(input: string): WatercraftIdentificationNumber {\n const result = WatercraftIdentificationNumber.tryParse(input);\n if (result === null) throw new Error(\"Invalid watercraft identification number.\");\n return result;\n }\n\n static isValid(input: string | null | undefined): boolean {\n return WatercraftIdentificationNumber.tryParse(input) !== null;\n }\n\n /**\n * Returns the number as it is marked on the hull, e.g. `NL-HXAB7A33G506` or\n * `ZZZ00001A020`.\n */\n static format(\n input: string | null | undefined,\n options?: WatercraftIdentificationNumberFormatOptions,\n ): string | null {\n const parsed = WatercraftIdentificationNumber.tryParse(input);\n if (parsed !== null) return parsed.formatted;\n return fallback(input, options);\n }\n\n /**\n * Returns the number in uppercase without separators, e.g. `NLHXAB7A33G506` or\n * `ZZZ00001A020`.\n */\n static normalize(\n input: string | null | undefined,\n options?: WatercraftIdentificationNumberFormatOptions,\n ): string | null {\n const parsed = WatercraftIdentificationNumber.tryParse(input);\n if (parsed !== null) return parsed.value;\n return fallback(input, options);\n }\n\n static isNormalized(input: string | null | undefined): boolean {\n return input != null && WatercraftIdentificationNumber.normalize(input) === input;\n }\n\n /**\n * Describes every invalid segment of the input, one issue per segment, or reports\n * it as valid.\n */\n static validate(input: string | null | undefined): ValidationResult {\n const issues: ValidationIssue[] = [];\n return WatercraftIdentificationNumber.tryParseCore(input, issues) !== null\n ? validResult(input)\n : invalidResult(input, issues);\n }\n\n /**\n * Finds watercraft identification number candidates in unstructured text. An ISO\n * 10087 number written with its hyphen is reported with medium confidence; one\n * without the hyphen, and a US HIN, are bare runs of letters and digits and\n * reported with low confidence. Results are heuristic and may include false\n * positives.\n */\n static findCandidatesInText(\n text: string,\n ): readonly TextCandidate<WatercraftIdentificationNumber>[] {\n if (!text) return [];\n\n const upper = toAsciiUpper(text);\n const out: TextCandidate<WatercraftIdentificationNumber>[] = [];\n const pattern = new RegExp(SCAN_PATTERN.source, SCAN_PATTERN.flags);\n let match: RegExpExecArray | null;\n\n while ((match = pattern.exec(upper)) !== null) {\n const value = WatercraftIdentificationNumber.tryParse(match[0]);\n if (value === null) continue;\n out.push(\n new TextCandidate<WatercraftIdentificationNumber>({\n startIndex: match.index,\n length: match[0].length,\n originalText: text.slice(match.index, match.index + match[0].length),\n typeName: \"WatercraftIdentificationNumber\",\n category: TextCandidateCategory.Vehicle,\n normalizedForm: value.toNormalizedString(),\n formattedForm: value.toString(),\n maskedForm: maskWatercraftIdentificationNumber(value),\n confidence: match[0].includes(\"-\") ? TextMatchConfidence.Medium : TextMatchConfidence.Low,\n value,\n }),\n );\n }\n\n return out;\n }\n\n /** Returns the number without separators, e.g. `NLHXAB7A33G506`. */\n toNormalizedString(): string {\n return this.value;\n }\n\n /** Returns the number as it is marked on the hull, e.g. `NL-HXAB7A33G506`. */\n toString(): string {\n return this.formatted;\n }\n\n equals(other: WatercraftIdentificationNumber | null | undefined): boolean {\n return other != null && this.value === other.value;\n }\n\n compareTo(other: WatercraftIdentificationNumber | null | undefined): number {\n if (other == null) return 1;\n return this.value < other.value ? -1 : this.value > other.value ? 1 : 0;\n }\n\n private static tryParseCore(\n input: string | null | undefined,\n issues: ValidationIssue[] | null,\n ): WatercraftIdentificationNumber | null {\n const fail = (reason: ValidationErrorReason, english: string, swedish: string): false => {\n issues?.push(new ValidationIssue(reason, english, swedish));\n return false;\n };\n\n if (isNullOrWhiteSpace(input)) {\n fail(ValidationErrorReason.InputIsEmpty, \"Input is empty or whitespace.\", \"V\u00E4rdet \u00E4r tomt.\");\n return null;\n }\n\n const cleaned = toAsciiUpper(sanitizeInput(input).replace(WHITESPACE_PATTERN, \"\"));\n\n if (cleaned.length > MAX_INPUT_LENGTH) {\n fail(\n ValidationErrorReason.InputTooLong,\n \"Input contains too many characters.\",\n \"V\u00E4rdet inneh\u00E5ller f\u00F6r m\u00E5nga tecken.\",\n );\n return null;\n }\n\n if (!ALLOWED_CHARACTERS_PATTERN.test(cleaned)) {\n fail(\n ValidationErrorReason.InvalidCharacters,\n \"Only letters A\u2013Z, digits and the hyphen after the country code are allowed.\",\n \"Endast bokst\u00E4verna A\u2013Z, siffror och bindestrecket efter landskoden \u00E4r till\u00E5tna.\",\n );\n return null;\n }\n\n const hyphenIndex = cleaned.indexOf(\"-\");\n const hasCountrySeparator = hyphenIndex >= 0;\n if (hasCountrySeparator && (hyphenIndex !== 2 || cleaned.indexOf(\"-\", hyphenIndex + 1) >= 0)) {\n fail(\n ValidationErrorReason.InvalidFormat,\n \"A hyphen is only allowed directly after the two-letter country code.\",\n \"Bindestreck f\u00E5r bara st\u00E5 direkt efter den tv\u00E5bokstaviga landskoden.\",\n );\n return null;\n }\n\n const compact = hasCountrySeparator\n ? cleaned.slice(0, hyphenIndex) + cleaned.slice(hyphenIndex + 1)\n : cleaned;\n const scheme =\n compact.length === ISO_LENGTH\n ? WatercraftIdentificationNumberScheme.Iso10087\n : compact.length === UNITED_STATES_LENGTH && !hasCountrySeparator\n ? WatercraftIdentificationNumberScheme.UnitedStatesHullIdentificationNumber\n : WatercraftIdentificationNumberScheme.Unknown;\n\n if (scheme === WatercraftIdentificationNumberScheme.Unknown) {\n fail(\n ValidationErrorReason.InvalidLength,\n \"Must be 14 characters after an ISO 10087 country code and hyphen, or 12 characters for a US HIN.\",\n \"M\u00E5ste vara 14 tecken enligt ISO 10087 (landskod, bindestreck och 12 tecken) eller 12 tecken f\u00F6r ett amerikanskt HIN.\",\n );\n return null;\n }\n\n const isIso = scheme === WatercraftIdentificationNumberScheme.Iso10087;\n const body = isIso ? compact.slice(2) : compact;\n let isValid = true;\n let country: Country | null = null;\n\n if (isIso) {\n country = resolveCountry(compact.slice(0, 2));\n if (country === null) {\n isValid = fail(\n ValidationErrorReason.UnknownCountryCode,\n \"The first two characters must be an ISO 3166-1 alpha-2 country code.\",\n \"De tv\u00E5 f\u00F6rsta tecknen m\u00E5ste vara en landskod enligt ISO 3166-1 alpha-2.\",\n );\n }\n }\n\n if (isIso && !ISO_MANUFACTURER_CODE_PATTERN.test(body.slice(0, 3))) {\n isValid = fail(\n ValidationErrorReason.InvalidManufacturerCode,\n \"The manufacturer code must be three letters or digits, except the digits 0 and 1.\",\n \"Tillverkarkoden m\u00E5ste vara tre bokst\u00E4ver eller siffror, men inte siffrorna 0 och 1.\",\n );\n }\n\n if (!isIso && !UNITED_STATES_MANUFACTURER_CODE_PATTERN.test(body.slice(0, 3))) {\n isValid = fail(\n ValidationErrorReason.InvalidManufacturerCode,\n \"The manufacturer code must be three letters or digits.\",\n \"Tillverkarkoden m\u00E5ste vara tre bokst\u00E4ver eller siffror.\",\n );\n }\n\n if (!SERIAL_NUMBER_PATTERN.test(body.slice(3, 8))) {\n isValid = fail(\n ValidationErrorReason.InvalidSerialNumber,\n \"The serial number must be five letters or digits, except the letters I, O and Q.\",\n \"Serienumret m\u00E5ste vara fem bokst\u00E4ver eller siffror, men inte bokst\u00E4verna I, O och Q.\",\n );\n }\n\n const monthCode = body[8]!;\n if (monthCode < \"A\" || monthCode > \"L\") {\n isValid = fail(\n ValidationErrorReason.InvalidMonthCode,\n \"The production month must be a letter from A (January) to L (December).\",\n \"Tillverkningsm\u00E5naden m\u00E5ste vara en bokstav fr\u00E5n A (januari) till L (december).\",\n );\n }\n\n if (!YEAR_DIGITS_PATTERN.test(body.slice(9, 12))) {\n isValid = fail(\n ValidationErrorReason.InvalidYearDigits,\n \"The production year and model year must be digits.\",\n \"Tillverknings\u00E5r och \u00E5rsmodell m\u00E5ste anges med siffror.\",\n );\n }\n\n if (!isValid) return null;\n\n return new WatercraftIdentificationNumber(compact, scheme, country);\n }\n}\n\n/**\n * Returns a watercraft identification number with only the country and manufacturer\n * codes visible, e.g. `NL-HXAB7A33G506` becomes `NL-HXA*********` and\n * `ZZZ00001A020` becomes `ZZZ*********`.\n */\nexport function maskWatercraftIdentificationNumber(win: WatercraftIdentificationNumber): string {\n const prefix =\n win.countryCode === null ? win.manufacturerCode : `${win.countryCode}-${win.manufacturerCode}`;\n return prefix + \"*\".repeat(win.formatted.length - prefix.length);\n}\n\nfunction resolveCountry(code: string): Country | null {\n if (!COUNTRY_CODE_PATTERN.test(code)) return null;\n const parsed = Country.tryParse(code);\n return parsed !== null && parsed.alpha2Code === code ? parsed : null;\n}\n\n/**\n * Upper-cases a\u2013z only and leaves every other code unit as it is, so the length and\n * match offsets are unchanged. `toUpperCase` maps some non-ASCII letters onto ASCII\n * (`\u0131` \u2192 `I`, `\u017F` \u2192 `S`), which would let a look-alike pass as A\u2013Z; the .NET port uses\n * the same ASCII-only rule.\n */\nfunction toAsciiUpper(text: string): string {\n return text.replace(LOWERCASE_ASCII_PATTERN, (c) => String.fromCharCode(c.charCodeAt(0) - 32));\n}\n\nfunction fallback(\n input: string | null | undefined,\n options?: WatercraftIdentificationNumberFormatOptions,\n): string | null {\n if (options?.fallbackToTrimmedInputWhenInvalid !== true || isNullOrWhiteSpace(input)) return null;\n return trimLikeDotnet(input);\n}\n\n/**\n * .NET `string.IsNullOrWhiteSpace` and `string.Trim()` use `char.IsWhiteSpace`, which counts\n * U+0085 and not U+FEFF \u2014 the reverse of `String.prototype.trim`. These mirror the .NET port so\n * the empty check and the fallback text agree for every input.\n */\nfunction isNullOrWhiteSpace(input: string | null | undefined): input is null | undefined {\n return input == null || DOTNET_WHITESPACE_ONLY_PATTERN.test(input);\n}\n\nfunction trimLikeDotnet(input: string): string {\n return input.replace(DOTNET_TRIM_PATTERN, \"\");\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -18,7 +18,7 @@ const PhoneNumberTestData = {
18
18
  get landlineMalmo() {
19
19
  return generateRange("04062804", 0, 99);
20
20
  },
21
- /** Landline Stockholm: 08-4650 04 00 through 08-4650 04 99 (100 numbers). */
21
+ /** Landline Stockholm: 08-465 004 00 through 08-465 004 99 (100 numbers). */
22
22
  get landlineStockholm() {
23
23
  return generateRange("08465004", 0, 99);
24
24
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/contact/phone-number-test-data.ts"],
4
- "sourcesContent": ["/**\n * PTS (Post- och telestyrelsen) reserves phone number ranges for use in fiction\n * and testing \u2014 these numbers are never assigned to real subscribers.\n *\n * {@link PhoneNumberTestData} enumerates every reserved number;\n * `PhoneNumber.isSwedishTestPhoneNumber` checks whether a parsed number falls in\n * a reserved range.\n *\n * Source: https://pts.se/internet-och-telefoni/telefonnummer-och-adressering/telefonnummer-till-bocker-och-filmer/\n */\nfunction generateRange(prefix: string, from: number, to: number): readonly string[] {\n const result: string[] = [];\n for (let i = from; i <= to; i++) {\n result.push(prefix + String(i).padStart(2, \"0\"));\n }\n return Object.freeze(result);\n}\n\nexport const PhoneNumberTestData = {\n /** Mobile: 070-174 06 05 through 070-174 06 99 (95 numbers). */\n get mobile(): readonly string[] {\n return generateRange(\"07017406\", 5, 99);\n },\n\n /** Landline Gothenburg: 031-390 06 00 through 031-390 06 99 (100 numbers). */\n get landlineGothenburg(): readonly string[] {\n return generateRange(\"03139006\", 0, 99);\n },\n\n /** Landline Malm\u00F6: 040-628 04 00 through 040-628 04 99 (100 numbers). */\n get landlineMalmo(): readonly string[] {\n return generateRange(\"04062804\", 0, 99);\n },\n\n /** Landline Stockholm: 08-4650 04 00 through 08-4650 04 99 (100 numbers). */\n get landlineStockholm(): readonly string[] {\n return generateRange(\"08465004\", 0, 99);\n },\n\n /** Landline Kiruna: 0980-31 92 00 through 0980-31 92 99 (100 numbers). */\n get landlineKiruna(): readonly string[] {\n return generateRange(\"09803192\", 0, 99);\n },\n\n /** All reserved test phone numbers across all ranges (495 numbers). */\n get all(): readonly string[] {\n return Object.freeze([\n ...PhoneNumberTestData.mobile,\n ...PhoneNumberTestData.landlineGothenburg,\n ...PhoneNumberTestData.landlineMalmo,\n ...PhoneNumberTestData.landlineStockholm,\n ...PhoneNumberTestData.landlineKiruna,\n ]);\n },\n};\n"],
4
+ "sourcesContent": ["/**\n * PTS (Post- och telestyrelsen) reserves phone number ranges for use in fiction\n * and testing \u2014 these numbers are never assigned to real subscribers.\n *\n * {@link PhoneNumberTestData} enumerates every reserved number;\n * `PhoneNumber.isSwedishTestPhoneNumber` checks whether a parsed number falls in\n * a reserved range.\n *\n * Source: https://pts.se/internet-och-telefoni/telefonnummer-och-adressering/telefonnummer-till-bocker-och-filmer/\n */\nfunction generateRange(prefix: string, from: number, to: number): readonly string[] {\n const result: string[] = [];\n for (let i = from; i <= to; i++) {\n result.push(prefix + String(i).padStart(2, \"0\"));\n }\n return Object.freeze(result);\n}\n\nexport const PhoneNumberTestData = {\n /** Mobile: 070-174 06 05 through 070-174 06 99 (95 numbers). */\n get mobile(): readonly string[] {\n return generateRange(\"07017406\", 5, 99);\n },\n\n /** Landline Gothenburg: 031-390 06 00 through 031-390 06 99 (100 numbers). */\n get landlineGothenburg(): readonly string[] {\n return generateRange(\"03139006\", 0, 99);\n },\n\n /** Landline Malm\u00F6: 040-628 04 00 through 040-628 04 99 (100 numbers). */\n get landlineMalmo(): readonly string[] {\n return generateRange(\"04062804\", 0, 99);\n },\n\n /** Landline Stockholm: 08-465 004 00 through 08-465 004 99 (100 numbers). */\n get landlineStockholm(): readonly string[] {\n return generateRange(\"08465004\", 0, 99);\n },\n\n /** Landline Kiruna: 0980-31 92 00 through 0980-31 92 99 (100 numbers). */\n get landlineKiruna(): readonly string[] {\n return generateRange(\"09803192\", 0, 99);\n },\n\n /** All reserved test phone numbers across all ranges (495 numbers). */\n get all(): readonly string[] {\n return Object.freeze([\n ...PhoneNumberTestData.mobile,\n ...PhoneNumberTestData.landlineGothenburg,\n ...PhoneNumberTestData.landlineMalmo,\n ...PhoneNumberTestData.landlineStockholm,\n ...PhoneNumberTestData.landlineKiruna,\n ]);\n },\n};\n"],
5
5
  "mappings": "AAUA,SAAS,cAAc,QAAgB,MAAc,IAA+B;AAClF,QAAM,SAAmB,CAAC;AAC1B,WAAS,IAAI,MAAM,KAAK,IAAI,KAAK;AAC/B,WAAO,KAAK,SAAS,OAAO,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,EACjD;AACA,SAAO,OAAO,OAAO,MAAM;AAC7B;AAEO,MAAM,sBAAsB;AAAA;AAAA,EAEjC,IAAI,SAA4B;AAC9B,WAAO,cAAc,YAAY,GAAG,EAAE;AAAA,EACxC;AAAA;AAAA,EAGA,IAAI,qBAAwC;AAC1C,WAAO,cAAc,YAAY,GAAG,EAAE;AAAA,EACxC;AAAA;AAAA,EAGA,IAAI,gBAAmC;AACrC,WAAO,cAAc,YAAY,GAAG,EAAE;AAAA,EACxC;AAAA;AAAA,EAGA,IAAI,oBAAuC;AACzC,WAAO,cAAc,YAAY,GAAG,EAAE;AAAA,EACxC;AAAA;AAAA,EAGA,IAAI,iBAAoC;AACtC,WAAO,cAAc,YAAY,GAAG,EAAE;AAAA,EACxC;AAAA;AAAA,EAGA,IAAI,MAAyB;AAC3B,WAAO,OAAO,OAAO;AAAA,MACnB,GAAG,oBAAoB;AAAA,MACvB,GAAG,oBAAoB;AAAA,MACvB,GAAG,oBAAoB;AAAA,MACvB,GAAG,oBAAoB;AAAA,MACvB,GAAG,oBAAoB;AAAA,IACzB,CAAC;AAAA,EACH;AACF;",
6
6
  "names": []
7
7
  }
@@ -197,7 +197,7 @@ class PhoneNumber {
197
197
  return this.countryCallingCode.value === dcc ? this.toLocalString() : this.toDisplayInternationalString();
198
198
  }
199
199
  const subscriber = this.digits.slice(2 + this.countryCallingCode.value.length);
200
- if (this.isSwedish) return formatSwedishLocal("0" + subscriber);
200
+ if (this.isSwedish) return formatSwedishLocal(subscriber);
201
201
  return "0" + subscriber;
202
202
  }
203
203
  toE164String() {
@@ -208,6 +208,7 @@ class PhoneNumber {
208
208
  }
209
209
  toDisplayInternationalString() {
210
210
  const subscriber = this.digits.slice(2 + this.countryCallingCode.value.length);
211
+ if (this.isSwedish) return formatSwedishInternational(subscriber);
211
212
  return "+" + this.countryCallingCode.value + " " + formatInternationalSubscriberDigits(this.countryCallingCode.value, subscriber);
212
213
  }
213
214
  toString() {
@@ -281,22 +282,43 @@ function formatInternationalSubscriberDigits(callingCode, digits) {
281
282
  return digits;
282
283
  }
283
284
  }
284
- function formatSwedishLocal(number) {
285
- const digits = number.replace(/^0+/, "");
286
- if (digits.length === 9) {
287
- return `0${digits.slice(0, 3)}-${digits.slice(3, 5)} ${digits.slice(5, 7)} ${digits.slice(7, 9)}`;
285
+ const SWEDISH_TWO_DIGIT_DESTINATION_CODES = /* @__PURE__ */ new Set([
286
+ ..."11 13 16 18 19 21 23 26 31 33 35 36 40 42 44 46 54 60 63 90".split(" "),
287
+ ..."10 20 70 71 72 73 74 75 76 77 79 99".split(" ")
288
+ ]);
289
+ const SWEDISH_THREE_DIGIT_DESTINATION_CODES_OVERRIDING_TWO_DIGIT = /* @__PURE__ */ new Set(["900"]);
290
+ function swedishDestinationCodeLength(nationalSignificantNumber) {
291
+ if (nationalSignificantNumber.startsWith("8")) return 1;
292
+ if (SWEDISH_THREE_DIGIT_DESTINATION_CODES_OVERRIDING_TWO_DIGIT.has(
293
+ nationalSignificantNumber.slice(0, 3)
294
+ )) {
295
+ return 3;
288
296
  }
289
- if (digits.length === 7) {
290
- const area = digits.slice(0, 1);
291
- const rest = digits.slice(1);
292
- return `0${area}-${rest.slice(0, 2)} ${rest.slice(2, 4)} ${rest.slice(4, 6)}`;
297
+ if (SWEDISH_TWO_DIGIT_DESTINATION_CODES.has(nationalSignificantNumber.slice(0, 2))) return 2;
298
+ return 3;
299
+ }
300
+ function groupSwedishSubscriberNumber(subscriber) {
301
+ if (subscriber.length === 8) {
302
+ return `${subscriber.slice(0, 3)} ${subscriber.slice(3, 6)} ${subscriber.slice(6)}`;
293
303
  }
294
- if (digits.length === 8) {
295
- const area = digits.slice(0, 1);
296
- const rest = digits.slice(1);
297
- return `0${area}-${rest.slice(0, 2)} ${rest.slice(2, 4)} ${rest.slice(4, 7)}`;
304
+ const firstGroupLength = subscriber.length % 2 === 1 ? 3 : 2;
305
+ const groups = [subscriber.slice(0, firstGroupLength)];
306
+ for (let i = firstGroupLength; i < subscriber.length; i += 2) {
307
+ groups.push(subscriber.slice(i, i + 2));
298
308
  }
299
- return number;
309
+ return groups.join(" ");
310
+ }
311
+ function splitSwedishNationalNumber(nationalSignificantNumber) {
312
+ const length = swedishDestinationCodeLength(nationalSignificantNumber);
313
+ return [nationalSignificantNumber.slice(0, length), nationalSignificantNumber.slice(length)];
314
+ }
315
+ function formatSwedishLocal(nationalSignificantNumber) {
316
+ const [destinationCode, subscriber] = splitSwedishNationalNumber(nationalSignificantNumber);
317
+ return `0${destinationCode}-${groupSwedishSubscriberNumber(subscriber)}`;
318
+ }
319
+ function formatSwedishInternational(nationalSignificantNumber) {
320
+ const [destinationCode, subscriber] = splitSwedishNationalNumber(nationalSignificantNumber);
321
+ return `+46 ${destinationCode} ${groupSwedishSubscriberNumber(subscriber)}`;
300
322
  }
301
323
  export {
302
324
  PhoneNumber,