@sroussey/parse-address
Version:
International street address parser for 220 jurisdictions (US, CA + 218 countries and territories), with SEC EDGAR country-code resolution
63 lines • 3.37 kB
JavaScript
// Address-string preprocessing applied before country dispatch.
//
// EDGAR / filing addresses frequently concatenate a legal-entity name ("street1")
// in front of the real street line, e.g.
// "BANK OF BERMUDA (CAYMAN) LIMITED, 6 FRONT STREET, HAMILTON HM11, BERMUDA"
// "c/o Maples Corporate Services Limited, PO Box 309, Ugland House, ..."
// The entity is not an address component and has no field to hold it, so the
// structured parse cannot use it and would otherwise fall back to dumping the
// whole line into `street`. Stripping a recognizable leading organization
// segment lets the real address parse. Because the cleaned string is used for
// BOTH the parse and the token-preservation check, nothing is scored as lost.
// Corporate/legal-entity suffixes that mark the leading segment as an org name.
// Anchored to the WHOLE last word (^…$) so that ordinary words ending in these
// letters — "Franco", "Francisco", "Eivissa" — are not mistaken for "co"/"sa".
const ORG_SUFFIX = /^(?:limited|ltd|l\.?l\.?c|inc|incorporated|corp|corporation|company|co|plc|l\.?l\.?p|l\.?p|g\.?p|trust|holdings|partners|ventures|capital|group|associates|foundation|fund|n\.?v|s\.?a\.?r\.?l|s\.?a|gmbh|a\.?g|b\.?v|pty|ulc|sarl|spa|s\.?p\.?a|s\.?r\.?l)\.?$/i;
// A leading "care of" / "attention" marker.
const CO_PREFIX = /^(?:c\/o|care of|attn\.?|attention|for the attention of)\b/i;
/**
* Remove a leading legal-entity / "c/o" segment from an address string. Returns
* the cleaned string and, when one was removed, the organization text. Only the
* FIRST comma-delimited segment is considered, and only when it does not begin
* with a house number (so a real "6 Front Street, ..." is never stripped) and
* there is still address content after it.
*/
export function stripLeadingOrganization(address) {
var _a;
let current = address.trim();
const removed = [];
// Peel leading org / "c/o" segments one at a time: EDGAR records routinely
// STACK them ("ABC HOLDINGS LTD, c/o Maples Corporate Services Limited, PO
// Box 309, Ugland House, ..."), so a single strip would leave an agent line
// at the head of the address.
for (;;) {
const comma = current.indexOf(",");
if (comma < 0)
break;
const first = current.slice(0, comma).trim();
const rest = current.slice(comma + 1).trim();
if (!first || !rest)
break;
// A segment that starts with a house number (or #/PO box) is an address
// line, never an organization -- stop peeling here.
if (/^[#\d]/.test(first) || /^p\.?o\.?\s*box\b/i.test(first))
break;
const isCareOf = CO_PREFIX.test(first);
// Compare the last word against the org-suffix set (ignoring a trailing
// parenthetical like "(Bermuda)" and any trailing period/paren).
const lastWord = (_a = first
.replace(/\([^)]*\)\s*$/, "")
.trim()
.split(/\s+/)
.pop()) !== null && _a !== void 0 ? _a : "";
const looksOrg = ORG_SUFFIX.test(lastWord);
if (!isCareOf && !looksOrg)
break;
removed.push(first);
current = rest;
}
if (!removed.length)
return { cleaned: address };
return { cleaned: current, organization: removed.join(", ") };
}
//# sourceMappingURL=preprocess.js.map