Skip to content

Support Canadian address parsing with French street type handling#208

Merged
sroussey merged 2 commits into
mainfrom
claude/sec-parse-deps-audit-qqklc1
Jul 22, 2026
Merged

Support Canadian address parsing with French street type handling#208
sroussey merged 2 commits into
mainfrom
claude/sec-parse-deps-audit-qqklc1

Conversation

@sroussey

Copy link
Copy Markdown
Contributor

Summary

Extends address normalization to support Canadian addresses alongside US addresses, with special handling for French-language street lines that lead with the street type (e.g., "123 Rue Principale") rather than trailing it. Upgrades the address parser library to v3.0.0-beta1 to enable country-specific parsing.

Key Changes

  • Multi-country parser support: Replaced single US parser with country-specific parsers (usAddressParser and caAddressParser), dispatched via new streetParserForCountry() function
  • French street type detection: Added FRENCH_LEADING_STREET_TYPES set to detect when a street line uses French leading-type ordering, preserving the original word order instead of reordering to English trailing-type format
  • Generalized street normalization: Renamed normalizeUSStreetAddress() to normalizeStreetAddress() and made it country-agnostic; now accepts a parser instance and handles both US and Canadian addresses
  • Loss guard: Implemented streetTokenCount() helper to detect when the parser would drop words (e.g., truncating "Avenue du Parc" to "Ave du"), falling back to raw street lines to prevent data loss
  • Parser output handling: Updated to extract civic_number_suffix from parser output and properly reconstruct house numbers; removed city re-extraction since EDGAR provides city as a structured field
  • Dependency upgrade: Updated @sroussey/parse-address from v2.4.2 to v3.0.0-beta1
  • Test coverage: Added four new test cases covering English Canadian streets, French Quebec streets, trailing direction abbreviation, and the loss-guard fallback

Implementation Details

  • The French street type detection works by examining the first token after the civic number in the source street line, allowing disambiguation of ambiguous words (Avenue, Place) by position rather than the word itself
  • The loss guard compares token counts before and after parsing; if tokens are lost, the raw street lines are preserved rather than persisting a truncated address
  • Return signature of normalizeStreetAddress() changed from 4-tuple (including city) to 3-tuple (street components only), since city is already a structured field from EDGAR

https://claude.ai/code/session_01Frvs9m4YyEfAoRVkibYSNN

claude added 2 commits July 21, 2026 21:49
Upgrade @sroussey/parse-address to 3.0.0-beta1 and route address street
normalization through the new country-aware parser: US and CA each get a
dedicated parser instance, other countries keep their raw street line.

- Preserve French leading-type ordering ("123 Rue Principale" is not
  reordered to "123 Principale Rue") by keying off the source token order.
- Add a token-preservation loss guard: the parser should only abbreviate
  and reorder, so a rebuilt line with fewer tokens (the beta CA parser
  truncates some French compound names like "Avenue du Parc") falls back
  to the raw lines instead of persisting a truncated address.
- Document why the parser's re-extracted city/postal_code are ignored:
  EDGAR supplies those as structured fields and the EDGAR zipCode is
  authoritative (also why the 3.0 zip->postal_code rename is a no-op here).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Frvs9m4YyEfAoRVkibYSNN
3.0.1 is the first Node-loadable ESM release (3.0.0-beta1 and 3.0.0 were
broken); it also ships two changes that affect this consumer:

- Token-preservation fallback: feeding the parser the full address string
  (with EDGAR's SEC region code, e.g. "A8") now trips the parser into
  returning the whole string as `street`. Fix: hand the parser only the
  street lines — city/state/postal are already structured from EDGAR and
  were never read back. Drop the now-unused city/state/zip parameters.
- The French-compound truncation the beta had is fixed upstream, so
  "1500 Avenue du Parc" normalizes to "1500 Ave du Parc" instead of falling
  back to the raw line; update that test accordingly.
- parseLocation now returns a typed ParsedAddress (was `any`), so the
  street-field filter/map chains need an explicit string type guard.

The local loss guard stays as defense-in-depth. Address suite 39/39 green;
project typechecks clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Frvs9m4YyEfAoRVkibYSNN
@sroussey
sroussey merged commit a632d30 into main Jul 22, 2026
1 check passed
@sroussey
sroussey deleted the claude/sec-parse-deps-audit-qqklc1 branch July 22, 2026 05:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants