UNPKG

@sroussey/parse-address

Version:

International street address parser for 220 jurisdictions (US, CA + 218 countries and territories), with SEC EDGAR country-code resolution

133 lines 5.98 kB
import { keepLastLocality } from "../_eu/localityChain.js"; /** * Ghana (GH) address configuration. * * Ghana has TWO addressing systems, both modelled here: * * (1) GhanaPostGPS digital address — a national digital address of the shape * "AA-NNN-NNNN" (two letters + 3-digit area + 4-digit unique), e.g. * "GA-183-8164" (Greater Accra) or "AK-039-5028" (Ashanti/Kumasi). The * first letter is the region, the second the district; "GA-183" alone is * the postcode. We capture the whole code as `postal_code`. Because Ghana * writes the code BEFORE the town ("GA-183-8164, Accra"), the country is * configured postcode-first (before-city), and the code is also recognised * when it trails a street ("Kingsway Road, GA-183-8164, Accra"). * * (2) Descriptive / physical address — "House No. 5, Kingsway Road, Adabraka, * Accra, Greater Accra", number-first with a trailing English type, an area * that is dropped, the town, and the region -> state. * * Postcode: the GhanaPostGPS code (letters+digits) OR absent (traditional Ghana * had NO postal codes and used PO boxes). Optional. * Region (-> state): the 16 regions (Greater Accra, Ashanti, Western, ...), * written after the city, optionally suffixed "Region". Output is a * 2-letter code (AA, AH, WP, ...). * PO Box: very common; box numbers often carry a 1-3 letter exchange prefix * ("P.O. Box CT 1234", "P. O. Box M 38"). * * KNOWN GAP: a BARE digital code with no town ("GA-183-8164" alone) has no * locality for the street/place grammar and parses as a street rather than a * postcode; such bare-code samples are marked __skip. Delivered forms carry a * town, which parses correctly. * * Sources: GhanaPostGPS (Ghana Post); Ghana Post GPS (Wikipedia); Regions and * District Codes (ghanapostgps.com); Smarty / PostGrid GH guides. See * research-gh.md. */ const TYPES = [ "Street", "Road", "Avenue", "Close", "Crescent", "Boulevard", "Drive", "Lane", "Way", "Circle", "Highway", "Court", "Place", "Walk", "Link", "Loop", "Ring", "Row", "Park", // abbreviations "St", "Rd", "Ave", "Av", "Dr", "Cres", "Blvd", "Hwy", ]; const TYPE_SHORT = { street: "ST", st: "ST", road: "RD", rd: "RD", avenue: "AVE", ave: "AVE", av: "AVE", close: "CL", crescent: "CRES", cres: "CRES", boulevard: "BLVD", blvd: "BLVD", drive: "DR", dr: "DR", lane: "LN", way: "WAY", circle: "CIR", highway: "HWY", hwy: "HWY", court: "CT", place: "PL", walk: "WLK", link: "LINK", loop: "LOOP", ring: "RING", row: "ROW", park: "PARK", }; // 16 regions -> ISO 3166-2:GH region code. const REGION_CODES = [ ["Greater Accra", "AA"], ["Western North", "WN"], ["Bono East", "BE"], ["North East", "NE"], ["Upper East", "UE"], ["Upper West", "UW"], ["Ashanti", "AH"], ["Central", "CP"], ["Eastern", "EP"], ["Northern", "NP"], ["Volta", "TV"], ["Western", "WP"], ["Bono", "BO"], ["Ahafo", "AF"], ["Oti", "OT"], ["Savannah", "SV"], ]; const REGION_MAP = {}; for (const [name, code] of REGION_CODES) { REGION_MAP[name.toLowerCase()] = code; REGION_MAP[`${name.toLowerCase()} region`] = code; } // Alternation: "<Name> Region" (longest) OR bare "<Name>"; longest-first. const REGION_ALT = [ ...REGION_CODES.map(([n]) => `${n.replace(/ /g, "\\s+")}\\s+Region`), ...REGION_CODES.map(([n]) => n.replace(/ /g, "\\s+")), ] .sort((a, b) => b.length - a.length) .join("|"); export const ghConfig = { code: "gh", country: "GH", countryNames: ["Ghana", "Republic of Ghana", "GHA", "GH"], order: "number-street", typePlacement: "suffix", // GhanaPostGPS code is written BEFORE the town. postalPlacement: "before-city", normalizeTypeCase: false, // GhanaPostGPS digital address: 2 letters, "-", 3-digit area, optional // "-", 4-digit unique. "GA-183" (postcode only) and "GA-183-8164" (full). postalPattern: "(?<postal_code>[A-Za-z]{2}-\\d{3}(?:-\\d{4})?)", postalFormat: (raw) => raw.toUpperCase().replace(/\s+/g, ""), // number: optional "House No."/"Plot"/"No."/"#" lead-in, a plot/house number // that may carry slashes ("F123/4" keeps "123/4"), optional glued letter. houseNumberPattern: "(?:House\\s+No\\.?\\s*|Plot\\s+(?:No\\.?\\s*)?|No\\.?\\s*|\\#\\s*)?(?<number>\\d+(?:[-/]\\d+)*)(?<civic_number_suffix>[A-Za-z](?![A-Za-z]))?", types: TYPES, typeDisplayMap: {}, typeShortCodeMap: TYPE_SHORT, // Keep the area+city chain together; drop leading area(s) in postNormalize. cityAllowsCommas: true, // Region after the city -> state. regionPattern: `(?<state>${REGION_ALT})`, regionMap: REGION_MAP, // Flat / House / Apartment / Suite lead the address. secUnitPlacement: "before", secUnitPattern: "(?<sec_unit_type>Flat|Apartment|Apt\\.?|House|Suite|Block|Floor|Room|Shop|Unit)\\.?\\s*(?<sec_unit_num>[\\w-]+)?", secUnitDisplayMap: { flat: "Flat", apartment: "Apartment", apt: "Apt", house: "House", suite: "Suite", block: "Block", floor: "Floor", room: "Room", shop: "Shop", unit: "Unit", }, // A leading building name ("Ridge Towers, Independence Avenue, Accra"). buildingKeywords: [ "Towers", "Tower", "House", "Centre", "Center", "Plaza", "Building", "Court", "Mall", "Complex", ], // Ghana Post boxes: box number often has a 1-3 letter exchange prefix. poBoxNames: ["P.O. Box", "PO Box", "P. O. Box", "Private Mail Bag", "PMB", "Post Box"], poBoxNumberPattern: "[A-Za-z]{0,3}\\s*\\d+", poBoxDisplayMap: { "p.o. box": "PO Box", "po box": "PO Box", "p. o. box": "PO Box", "private mail bag": "PMB", pmb: "PMB", "post box": "PO Box", }, // Collapse the "area, city" chain to the routing city + dropped area(s). postNormalize: (parsed) => keepLastLocality(parsed), }; export default ghConfig; //# sourceMappingURL=config.js.map