Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/codex-macos-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Codex macOS Validation

on:
workflow_dispatch:

jobs:
swift-test:
name: Swift tests
runs-on: macos-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Run SwiftPM tests
run: swift test

xcodebuild:
name: Xcode build
runs-on: macos-latest
needs: swift-test

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Build iOS framework
run: xcodebuild -project "PhoneNumberKit.xcodeproj" -scheme "PhoneNumberKit" -destination "generic/platform=iOS" build

- name: Build macOS framework
run: xcodebuild -project "PhoneNumberKit.xcodeproj" -scheme "PhoneNumberKit-macOS" -destination "generic/platform=macOS" build
8 changes: 4 additions & 4 deletions PhoneNumberKit/ParseManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ final class ParseManager {
}

// Last attempt: try to parse the number as-is with the region's default country code
if let result = try validPhoneNumber(from: nationalNumber, using: regionMetadata, countryCode: regionMetadata.countryCode, ignoreType: ignoreType, numberString: numberString, numberExtension: numberExtension) {
if let result = try validPhoneNumber(from: nationalNumber, using: regionMetadata, countryCode: regionMetadata.countryCode, ignoreType: ignoreType, numberString: matchedNumber, numberExtension: numberExtension) {
return result
}

// Final fallback for countryCode == 0: try all territories with the same country code as the region
// This handles cases where a number from one NANP territory (e.g., US) is parsed with another NANP region (e.g., AS, PR)
return try tryTerritoriesWithCode(regionMetadata.countryCode, nationalNumber: nationalNumber, excludingRegion: regionMetadata.codeID, ignoreType: ignoreType, numberString: numberString, numberExtension: numberExtension)
return try tryTerritoriesWithCode(regionMetadata.countryCode, nationalNumber: nationalNumber, excludingRegion: regionMetadata.codeID, ignoreType: ignoreType, numberString: matchedNumber, numberExtension: numberExtension)
}

// STEP 6: Update metadata if extracted country code differs from region's default
Expand All @@ -106,14 +106,14 @@ final class ParseManager {
}

// Attempt to create a valid phone number with the extracted country code
if let result = try validPhoneNumber(from: nationalNumber, using: regionMetadata, countryCode: countryCode, ignoreType: ignoreType, numberString: numberString, numberExtension: numberExtension) {
if let result = try validPhoneNumber(from: nationalNumber, using: regionMetadata, countryCode: countryCode, ignoreType: ignoreType, numberString: matchedNumber, numberExtension: numberExtension) {
return result
}

// STEP 7: Final fallback - try all territories with the same country code
// Some country codes are shared by multiple territories (e.g., +1 for US, CA, etc.)
// Try each territory's metadata to see if the number is valid in any of them
return try tryTerritoriesWithCode(countryCode, nationalNumber: nationalNumber, excludingRegion: regionMetadata.codeID, ignoreType: ignoreType, numberString: numberString, numberExtension: numberExtension)
return try tryTerritoriesWithCode(countryCode, nationalNumber: nationalNumber, excludingRegion: regionMetadata.codeID, ignoreType: ignoreType, numberString: matchedNumber, numberExtension: numberExtension)
}

// Parse task
Expand Down
6 changes: 6 additions & 0 deletions PhoneNumberKit/RegexManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ final class RegexManager {
let fallBackMatches = try regexMatches(PhoneNumberPatterns.validPhoneNumberPattern, string: string)
if let firstMatch = fallBackMatches.first {
return firstMatch
}

let embeddedPhoneNumberPattern = #"(?<![\w@])\+?\d[\d\s().-]{6,}\d(?![\w@])"#
let embeddedMatches = try regexMatches(embeddedPhoneNumberPattern, string: string)
if let firstMatch = embeddedMatches.first {
return firstMatch
} else {
throw PhoneNumberError.invalidNumber
}
Expand Down
9 changes: 9 additions & 0 deletions PhoneNumberKitTests/PhoneNumberUtilityParsingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,15 @@ final class PhoneNumberUtilityParsingTests: XCTestCase {
try XCTAssertNotNil(sut.parse(address, withRegion: "JM"))
}

func testParsedNumberStringDoesNotKeepSurroundingContactInfo() throws {
let input = "Jane Doe <jane@example.com> mobile +1 650 253 0000"
let number = try sut.parse(input, withRegion: "US")

XCTAssertEqual(number.numberString, "+1 650 253 0000")
XCTAssertFalse(number.numberString.contains("jane@example.com"))
XCTAssertFalse(number.numberString.contains("Jane Doe"))
}

func testRegionCountryCodeConflict() {
XCTAssertThrowsError(try sut.parse("212-2344", withRegion: "US")) { error in
XCTAssertEqual(error as? PhoneNumberError, .invalidNumber)
Expand Down
Loading