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.9 kB
import { keepLastLocality } from "../_eu/localityChain.js"; /** * Zambia (ZM) address configuration. * * Order: house/stand NUMBER first, then the street name + trailing English type * ("10 Great East Road") — number-first, suffix type. Zambian addresses * commonly lead with a cadastral "Stand No. <n>" or "Plot <n>". * Type: trailing English suffix (Road, Street, Avenue, Close, Drive, ...). Many * roads are type-less; the type must be optional. * Locality: an AREA / township / suburb (Rhodes Park, Kabulonga, Woodlands, * Northmead, Roma, Olympia, ...) sits between the street and the routing * city. As in KE/ZA the comma chain is kept together and the leading * area(s) are dropped in postNormalize, keeping the last locality (city). * Postcode: a 5-digit numeric postcode exists (e.g. Lusaka "10101") but is very * frequently OMITTED. Written AFTER the city (after-city). Optional. * Province (-> state): the 10 provinces (Lusaka, Copperbelt, Southern, ...) are * occasionally written. Because several province names duplicate a city * (Lusaka, Central), only the explicit "<Name> Province" form (plus the * unambiguous "Copperbelt") is recognised in the county slot, so a bare * "Area, City" pair is never mis-split with the city taken as the province. * PO Box: very common ("P.O. Box 30234, Lusaka"). The box replaces the * thoroughfare. * * Sources: Zambia Postal Services Corporation (Zampost); UPU S42 ZM template; * Smarty / PostGrid / GeoPostcodes ZM address guides. See research-zm.md. */ const TYPES = [ "Road", "Street", "Avenue", "Close", "Crescent", "Boulevard", "Drive", "Lane", "Way", "Court", "Place", "Terrace", "Circle", "Ring", "Loop", "Rise", "Grove", "Row", "Park", "Gardens", "Walk", "Hill", "Highway", "Mews", "Bypass", // abbreviations "Rd", "St", "Ave", "Av", "Dr", "Cl", "Cres", "Blvd", "Hwy", ]; const TYPE_SHORT = { road: "RD", rd: "RD", street: "ST", st: "ST", avenue: "AVE", ave: "AVE", av: "AVE", close: "CL", cl: "CL", crescent: "CRES", cres: "CRES", boulevard: "BLVD", blvd: "BLVD", drive: "DR", dr: "DR", lane: "LN", way: "WAY", court: "CT", place: "PL", terrace: "TER", circle: "CIR", ring: "RING", loop: "LOOP", rise: "RISE", grove: "GR", row: "ROW", park: "PARK", gardens: "GDNS", walk: "WLK", hill: "HL", highway: "HWY", hwy: "HWY", mews: "MEWS", bypass: "BYP", }; // 10 provinces. Recognised only in the explicit "<Name> Province" form (plus the // unambiguous single-word "Copperbelt"/"North-Western"), so a bare province name // that duplicates a city (Lusaka, Central) never eats the routing city. const PROVINCES = [ "Lusaka", "Copperbelt", "Southern", "Eastern", "Northern", "Western", "Central", "Luapula", "Muchinga", "North-Western", "North Western", ]; const PROVINCE_ALT = [ ...PROVINCES.map((p) => `${p.replace(/ /g, "\\s+")}\\s+Province`), "Copperbelt", "North-Western", ] .sort((a, b) => b.length - a.length) .join("|"); const REGION_MAP = {}; for (const p of PROVINCES) { REGION_MAP[`${p.toLowerCase()} province`] = p; } REGION_MAP["copperbelt"] = "Copperbelt"; REGION_MAP["north-western"] = "North-Western"; export const zmConfig = { code: "zm", country: "ZM", countryNames: ["Zambia", "Republic of Zambia", "ZMB", "ZM"], order: "number-street", typePlacement: "suffix", postalPlacement: "after-city", normalizeTypeCase: false, // 5-digit postcode, after the city; optional (frequently omitted). postalPattern: "(?<postal_code>\\d{5})", // number FIRST, optional "Stand"/"Plot"/"No."/"#" lead-in, optional // range/subdivision ("2374/M"), optional glued letter suffix. houseNumberPattern: "(?:Stand\\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, // Only an explicit province form may land in the state slot. countyPattern: `(?:${PROVINCE_ALT})`, regionMap: REGION_MAP, // Flat / Apartment / House / 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 ("Findeco House, Cairo Road, Lusaka"). buildingKeywords: [ "House", "Tower", "Towers", "Centre", "Center", "Plaza", "Building", "Mall", "Complex", "Arcade", ], // A Zambian Private Bag number may carry a 1-2 letter exchange prefix // ("Private Bag E123"); a plain PO Box number stays all-digits. poBoxNumberPattern: "[A-Za-z]{0,2}\\s*\\d+", poBoxNames: ["P.O. Box", "PO Box", "P. O. Box", "P O Box", "Post Box", "Private Bag", "P/Bag"], poBoxDisplayMap: { "p.o. box": "PO Box", "po box": "PO Box", "p. o. box": "PO Box", "p o box": "PO Box", "post box": "PO Box", "private bag": "Private Bag", "p/bag": "Private Bag", }, // Collapse the "area, city" chain to the routing city + dropped area(s). The // "Stand"/"Plot" number lead-ins are consumed but not emitted, so they are // exempted from the token-preservation guard here (as PK does for "House"/"Plot"). postNormalize: (parsed) => { keepLastLocality(parsed, ["Stand", "Plot"]); }, }; export default zmConfig; //# sourceMappingURL=config.js.map