@sroussey/parse-address
Version:
International street address parser for 220 jurisdictions (US, CA + 218 countries and territories), with SEC EDGAR country-code resolution
127 lines • 5.76 kB
JavaScript
import { keepLastLocality } from "../_eu/localityChain.js";
/**
* Nepal (NP) address configuration.
*
* Order: an optional house NUMBER first ("House No. 41", often omitted), then a
* SUFFIX-type thoroughfare / tole name ("Rohini Marg", "Putali Sadak",
* "Kamal Pokhari"). Many localities are a bare tole (neighbourhood) with
* NO number and NO type, which is the dominant Nepali form.
* Type: trailing Nepali road suffix -- Marg/Marga (road/avenue), Sadak/Sarak
* (road), Path, Chowk (square), Tole (quarter), Bato (road), plus English
* Road/Lane. Type is frequently absent (bare tole -> dropped null).
* Ward: Nepali municipal addresses carry a WARD number ("Ward No. 26"), written
* after the tole and before the city. It is modelled as a trailing
* secondary unit (sec_unit_type "Ward No", sec_unit_num N).
* Postcode: a 5-digit code exists but is VERY commonly OMITTED (Nepal's postal
* code system is little used in practice), so it is optional; when present
* it is written AFTER the city ("Kathmandu 44600").
* Province: the 7 provinces (Bagmati, Gandaki, Lumbini, ...) -> `state` as a
* short code. Written EITHER before the postcode (county slot) OR after it
* (helper `np_state`). District names (Kathmandu, Lalitpur, ...) double as
* cities and are NOT treated as the province.
* Locality chain: an older-ward locality ("Old Baneshwor-10") or a suburb sits
* between the tole and the city; the IN/ZA locality-drop trick keeps the
* routing city and drops the rest.
*
* KNOWN GAPS (see research-np.md): a ward glued to the locality with a dash
* ("Baneshwor-10") is dropped rather than surfaced; a bare tole-only line with no
* city; and native Devanagari-script addresses are documented failure modes.
*/
const TYPES = [
"Marga", "Sadak", "Sarak", "Chowk", "Marg", "Tole", "Bato", "Road", "Lane",
"Path", "Galli",
];
const TYPE_SHORT = {
marg: "MARG", marga: "MARG",
sadak: "SADAK", sarak: "SADAK",
chowk: "CHOWK",
tole: "TOLE",
bato: "BATO",
road: "RD",
lane: "LN",
path: "PATH",
galli: "GALLI",
};
// 7 provinces -> short code. Older numeric names ("Province No. 1") not modelled.
const REGION_MAP = {
koshi: "P1", kosi: "P1",
madhesh: "P2", madhes: "P2",
bagmati: "P3",
gandaki: "P4",
lumbini: "P5",
karnali: "P6",
sudurpashchim: "P7", sudurpaschim: "P7",
};
const PROVINCES = [
"Sudurpashchim", "Sudurpaschim", "Bagmati", "Gandaki", "Lumbini", "Karnali",
"Madhesh", "Madhes", "Koshi", "Kosi",
];
// Accept an optional trailing "Province"/"Pradesh" word after the name.
const PROV_ALT = "(?:" + PROVINCES.map((s) => s.replace(/ /g, "\\s+")).join("|") +
")(?:\\s+(?:Province|Pradesh))?";
export const npConfig = {
code: "np",
country: "NP",
countryNames: ["Nepal", "NPL", "NP"],
order: "number-street",
typePlacement: "suffix",
postalPlacement: "after-city",
normalizeTypeCase: false,
// OPTIONAL 5-digit postcode after the city, then an OPTIONAL trailing province
// captured in a helper group folded to `state` in postNormalize.
postalPattern: `(?<postal_code>\\d{5})(?:[\\s,]+(?<np_state>${PROV_ALT}))?`,
// Optional "House No."/"H. No."/"No." lead-in, number with an optional "/n" or
// "-n" part, optional glued letter suffix. The number is frequently absent.
houseNumberPattern: "(?:House\\s+No\\.?\\s*|H\\.?\\s*No\\.?\\s*|No\\.?\\s*)?(?<number>\\d+(?:[-/]\\d+)?)(?<civic_number_suffix>[A-Za-z](?![A-Za-z]))?",
types: TYPES,
typeDisplayMap: {},
typeShortCodeMap: TYPE_SHORT,
// Keep the suburb/locality chain together; 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,
// Ward number as a trailing secondary unit ("Ward No. 26"). Flat/Apartment/
// Floor also lead the address for apartment blocks.
secUnitPlacement: "after",
secUnitPattern: "(?<sec_unit_type>Ward\\s+No\\.?|Ward)\\.?\\s*(?<sec_unit_num>\\d+)",
secUnitDisplayMap: {
"ward no": "Ward No",
ward: "Ward",
},
// A leading building whose name ends in a building keyword.
buildingKeywords: [
"Bhawan", "Bhavan", "Tower", "Towers", "Complex", "Plaza", "Building",
"Centre", "Center", "Sadan", "Niwas",
],
// Nepal Post box forms.
poBoxNames: ["PO Box", "P.O. Box", "GPO Box", "G.P.O. Box", "Post Box"],
poBoxDisplayMap: {
"po box": "PO Box",
"p.o. box": "PO Box",
"gpo box": "GPO Box",
"g.p.o. box": "GPO Box",
"post box": "PO Box",
},
// Fold the helper `np_state` (province after the postcode) into `state`, then
// drop the leading locality chain, keeping the routing city.
postNormalize: (parsed) => {
var _a;
if (typeof parsed.np_state === "string" && parsed.np_state) {
const key = parsed.np_state
.toLowerCase()
.replace(/\s+(province|pradesh)$/, "")
.replace(/\s+/g, " ")
.trim();
if (!parsed.state)
parsed.state = (_a = REGION_MAP[key]) !== null && _a !== void 0 ? _a : parsed.np_state;
delete parsed.np_state;
}
// "House" is a label-only lead-in (like the stripped "No"): it carries no
// output field, so it is exempted from the token-preservation guard.
keepLastLocality(parsed, ["House"]);
},
};
export default npConfig;
//# sourceMappingURL=config.js.map