UNPKG

@sroussey/parse-address

Version:

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

135 lines 5.84 kB
import { keepLastLocality } from "../_eu/localityChain.js"; /** * Sri Lanka (LK) address configuration. * * Order: house NUMBER first (often an assessment number "478", "56/2", or a * "No." lead-in "No. 123"), then a SUFFIX-type thoroughfare name * ("Galle Road", "Baseline Road", "Bauddhaloka Mawatha", "1st Lane"). * Type: trailing English/Sinhala suffix -- Road/Rd, Street/St, Lane, Avenue/Ave, * Place, Mawatha (Sinhala avenue/road, romanised), Terrace, Crescent, * Junction, Drive, Row, Vidiya (Sinhala street), Path. Many roads carry * no type ("Galle Face", type-less -> dropped null). * Postcode: 5-digit numeric, written AFTER the city ("Kandy 20000", * "Maharagama 10230", "Colombo 00300"). Leading zeros are significant * (Colombo codes start 00xxx), so it is captured as `\d{5}` verbatim. * Province: the 9 provinces (Western, Central, Southern, ...) -> `state` as a * 2-letter code (WP/CP/SP/...). Written EITHER before the postcode (folded * via the county slot) OR after it (helper `lk_state` group inside the * postal pattern). District/suburb names are localities, not the province. * Locality chain: a suburb/area (Bambalapitiya, Nugegoda, Dehiwala, ...) commonly * sits between the street and the city. Because the postcode is after the * city, the IN/ZA trick applies: keep the comma chain in the city capture, * then drop the leading localities and keep the routing city. * * KNOWN GAPS (see research-lk.md): the Colombo district-number written INTO the * city ("Colombo 3" / "Colombo 03"); a glued "City-NN" ward-style suffix; and * native Sinhala/Tamil-script addresses are documented failure modes. */ // Trailing thoroughfare types, longest / multi-word first (also handled by the ruleset). const TYPES = [ "Cross Street", "Mawatha", "Terrace", "Crescent", "Junction", "Avenue", "Street", "Place", "Drive", "Vidiya", "Road", "Lane", "Path", "Row", "Mw", "Rd", "St", "Ave", ]; const TYPE_SHORT = { road: "RD", rd: "RD", street: "ST", st: "ST", "cross street": "CRST", lane: "LN", avenue: "AVE", ave: "AVE", place: "PL", mawatha: "MW", mw: "MW", terrace: "TER", crescent: "CRES", junction: "JCT", drive: "DR", row: "ROW", vidiya: "VID", path: "PATH", }; // 9 provinces -> ISO 3166-2:LK-style 2-letter code. Multi-word longest-first. const REGION_MAP = { "north western": "NW", "north central": "NC", "sabaragamuwa": "SG", "western": "WP", "central": "CP", "southern": "SP", "northern": "NP", "eastern": "EP", "uva": "UV", }; const PROVINCES = [ "North Western", "North Central", "Sabaragamuwa", "Western", "Central", "Southern", "Northern", "Eastern", "Uva", ]; // Accept an optional trailing "Province" word after the name. const PROV_ALT = "(?:" + PROVINCES.map((s) => s.replace(/ /g, "\\s+")).join("|") + ")(?:\\s+Province)?"; export const lkConfig = { code: "lk", country: "LK", countryNames: ["Sri Lanka", "LKA", "LK", "Ceylon"], order: "number-street", typePlacement: "suffix", postalPlacement: "after-city", normalizeTypeCase: false, // 5-digit postcode after the city, then an OPTIONAL trailing province captured // in a helper group folded to `state` in postNormalize ("Kandy 20000, Central // Province"). postalPattern: `(?<postal_code>\\d{5})(?:[\\s,]+(?<lk_state>${PROV_ALT}))?`, // Optional "No."/"#" lead-in, an assessment number that may carry a slash or // hyphen ("56/2", "12-3"), and an optional glued letter suffix. houseNumberPattern: "(?:No\\.?\\s*|\\#\\s*)?(?<number>\\d+(?:[-/]\\d+)*)(?<civic_number_suffix>[A-Za-z](?![A-Za-z]))?", types: TYPES, typeDisplayMap: {}, typeShortCodeMap: TYPE_SHORT, // Keep the suburb/area chain together; the routing city is the LAST locality // before the province/postcode (postNormalize drops the earlier ones). A real // province written before the postcode falls into the county slot. cityAllowsCommas: true, countyPattern: `(?:${PROV_ALT})`, regionMap: REGION_MAP, // Flat / Apartment / Floor / Level / Unit / Suite lead the address. secUnitPlacement: "before", secUnitPattern: "(?<sec_unit_type>Flat|Apartment|Apt\\.?|Floor|Level|Unit|Suite|Room)\\.?\\s*(?<sec_unit_num>[\\w-]+)?", secUnitDisplayMap: { flat: "Flat", apartment: "Apartment", apt: "Apt", floor: "Floor", level: "Level", unit: "Unit", suite: "Suite", room: "Room", }, // A leading building whose name ends in a building keyword ("World Trade // Centre, ...", "Liberty Plaza, ..."). buildingKeywords: [ "Towers", "Tower", "Building", "Buildings", "Centre", "Center", "Complex", "Chambers", "Plaza", "Arcade", "Mawatha House", "House", ], // Sri Lanka Post box forms. poBoxNames: ["PO Box", "P.O. Box", "Post Box"], poBoxDisplayMap: { "po box": "PO Box", "p.o. box": "PO Box", "post box": "PO Box", }, // Fold the helper `lk_state` (province after the postcode) into `state`, then // drop the leading suburb chain, keeping the routing city. postNormalize: (parsed) => { var _a; if (typeof parsed.lk_state === "string" && parsed.lk_state) { const key = parsed.lk_state .toLowerCase() .replace(/\s+province$/, "") .replace(/\s+/g, " ") .trim(); if (!parsed.state) parsed.state = (_a = REGION_MAP[key]) !== null && _a !== void 0 ? _a : parsed.lk_state; delete parsed.lk_state; } keepLastLocality(parsed); }, }; export default lkConfig; //# sourceMappingURL=config.js.map