vladdress
Version:
Lightweight Street Address Parser Written in TypeScript
106 lines (105 loc) • 5.47 kB
JavaScript
;
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;