UNPKG

vladdress

Version:

Lightweight Street Address Parser Written in TypeScript

106 lines (105 loc) 5.47 kB
"use strict"; exports.__esModule = true; exports.parseStreetAddress = exports.matchStreetAddress = exports.matchesStreetAddress = exports.streetAddressRegex = void 0; var strings_1 = require("../utils/strings"); var usStreetTypes = require("../data/us/street-types.json"); exports.streetAddressRegex = /^(?<streetNum>(?:\d+\w*|\w*\d+)?)?\s*(?<streetName>.+)$/i; var matchesStreetAddress = function (input) { return !!input && exports.streetAddressRegex.test(input); }; exports.matchesStreetAddress = matchesStreetAddress; var matchStreetAddress = function (input) { return (input === null || input === void 0 ? void 0 : input.match(exports.streetAddressRegex)) || null; }; exports.matchStreetAddress = matchStreetAddress; var usStreetDirectional = { north: "N", northeast: "NE", east: "E", southeast: "SE", south: "S", southwest: "SW", west: "W", northwest: "NW" }; var parseStreetAddress = function (streetString) { var _a, _b, _c; if (!streetString) { throw new Error('No Street String Passed to parseStreetAddress'); } var match = (0, exports.matchStreetAddress)(streetString); var resultStreetName; var resultAddressLine1; var resultAddressLine2; var resultStreetDirection; var resultStreetSuffix; var resultStreetNumber; if (match) { var fullStreetName = (_a = match.groups) === null || _a === void 0 ? void 0 : _a.streetName; if (fullStreetName && /\w\s+ave(?:nue)?.?\s\w/i.test(fullStreetName)) { resultStreetName = (_b = (0, strings_1.replaceCaseInsensitive)(fullStreetName, 'avenue', true, 'Ave')) === null || _b === void 0 ? void 0 : _b.replace(/\./g, ''); } else { resultAddressLine1 = match[0]; streetString = streetString.replace(resultAddressLine1, "").trim(); // Carve off the first address line if (streetString && streetString.length > 0) { // Check if line2 data was already parsed if (resultAddressLine2 && resultAddressLine2.length > 0) { throw new Error('Can not parse address. Too many address lines.'); } else { resultAddressLine2 = streetString; } } var streetParts = resultAddressLine1.split(' '); // Check if directional is last element var uppercaseLine1_1 = resultAddressLine1.toUpperCase(); var direction = Object.keys(usStreetDirectional).find(function (key) { return uppercaseLine1_1.endsWith(' ' + usStreetDirectional[key]) || uppercaseLine1_1.endsWith(' ' + key.toUpperCase()); }); if (direction) { resultStreetDirection = usStreetDirectional[direction]; streetParts.pop(); } // If there are only 2 street parts (number and name) then its likely missing a "real" suffix and the street name just happened to match a suffix if (streetParts.length > 2) { // Remove '.' if it follows streetSuffix var originalStreetType = streetParts[streetParts.length - 1]; streetParts[streetParts.length - 1] = originalStreetType.replace(/\.$/, ''); var lowercaseStreetType = streetParts[streetParts.length - 1].toLowerCase(); var streetType = usStreetTypes[lowercaseStreetType]; if (streetType) { resultStreetSuffix = (0, strings_1.toTitleCase)(streetType.toLowerCase()); fullStreetName = (0, strings_1.replaceCaseInsensitive)(fullStreetName, originalStreetType, true); } } resultStreetName = fullStreetName === null || fullStreetName === void 0 ? void 0 : fullStreetName.trim(); // Assume street name is everything in the middle var lowercaseStreetName_1 = resultStreetName === null || resultStreetName === void 0 ? void 0 : resultStreetName.toLowerCase(); if (direction && resultStreetName) { resultStreetName = resultStreetName === null || resultStreetName === void 0 ? void 0 : resultStreetName.replace(/\s\w+$/, '').trim(); } if (lowercaseStreetName_1 && !resultStreetSuffix) { var foundEnding = Object.keys(usStreetTypes).find(function (type) { return lowercaseStreetName_1.endsWith(' ' + type); }); if (foundEnding) { resultStreetName = resultStreetName === null || resultStreetName === void 0 ? void 0 : resultStreetName.substring(0, resultStreetName.length - foundEnding.length).trim(); } } } resultStreetName = (0, strings_1.toTitleCase)(resultStreetName || '') .replace('Fm', 'FM'); resultStreetNumber = (_c = match.groups) === null || _c === void 0 ? void 0 : _c.streetNum; resultAddressLine1 = [resultStreetNumber, resultStreetName, resultStreetSuffix, resultStreetDirection].filter(function (s) { return !!s; }).join(" "); } return { streetName: resultStreetName, line1: resultAddressLine1, line2: resultAddressLine2, streetDirection: resultStreetDirection, streetSuffix: resultStreetSuffix, streetNumber: resultStreetNumber, streetString: streetString }; }; exports.parseStreetAddress = parseStreetAddress;