@mailwoman/corpus 9.0.0 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/data/PROVENANCE.md +227 -0
- package/data/reviewed-ve-postcode-tuples.json +74 -0
- package/data/sub-venue-lexicon.json +18269 -0
- package/out/src/adapters/ban/adapter.d.ts +1 -1
- package/out/src/adapters/ban/adapter.d.ts.map +1 -1
- package/out/src/adapters/ban/adapter.js +5 -4
- package/out/src/adapters/ban/adapter.js.map +1 -1
- package/out/src/adapters/fcc-bdc/adapter.d.ts +1 -1
- package/out/src/adapters/fcc-bdc/adapter.d.ts.map +1 -1
- package/out/src/adapters/fcc-bdc/adapter.js +3 -3
- package/out/src/adapters/fcc-bdc/adapter.js.map +1 -1
- package/out/src/adapters/geonames/adapter.d.ts +1 -1
- package/out/src/adapters/geonames/adapter.d.ts.map +1 -1
- package/out/src/adapters/geonames/adapter.js +2 -2
- package/out/src/adapters/geonames/adapter.js.map +1 -1
- package/out/src/adapters/geonames-postal/adapter.d.ts +1 -1
- package/out/src/adapters/geonames-postal/adapter.d.ts.map +1 -1
- package/out/src/adapters/geonames-postal/adapter.js +3 -3
- package/out/src/adapters/geonames-postal/adapter.js.map +1 -1
- package/out/src/adapters/gnaf/adapter.d.ts +1 -1
- package/out/src/adapters/gnaf/adapter.d.ts.map +1 -1
- package/out/src/adapters/gnaf/adapter.js +2 -2
- package/out/src/adapters/gnaf/adapter.js.map +1 -1
- package/out/src/adapters/gnaf/assemble.js +1 -1
- package/out/src/adapters/gnaf/assemble.js.map +1 -1
- package/out/src/adapters/index.d.ts +1 -1
- package/out/src/adapters/index.d.ts.map +1 -1
- package/out/src/adapters/index.js +1 -1
- package/out/src/adapters/index.js.map +1 -1
- package/out/src/adapters/openaddresses/adapter.d.ts +1 -1
- package/out/src/adapters/openaddresses/adapter.d.ts.map +1 -1
- package/out/src/adapters/openaddresses/adapter.js +3 -3
- package/out/src/adapters/openaddresses/adapter.js.map +1 -1
- package/out/src/adapters/overture/adapter.d.ts +1 -1
- package/out/src/adapters/overture/adapter.d.ts.map +1 -1
- package/out/src/adapters/overture/adapter.js +2 -2
- package/out/src/adapters/overture/adapter.js.map +1 -1
- package/out/src/adapters/state-hi-schools/adapter.d.ts +1 -1
- package/out/src/adapters/state-hi-schools/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-hi-schools/adapter.js +7 -6
- package/out/src/adapters/state-hi-schools/adapter.js.map +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.d.ts +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.js +12 -7
- package/out/src/adapters/state-ia-contractors/adapter.js.map +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.d.ts +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.js +12 -18
- package/out/src/adapters/state-ny-notaries/adapter.js.map +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.d.ts +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.js +12 -7
- package/out/src/adapters/state-tx-notaries/adapter.js.map +1 -1
- package/out/src/adapters/synth-po-box/adapter.d.ts +3 -3
- package/out/src/adapters/synth-po-box/adapter.d.ts.map +1 -1
- package/out/src/adapters/synth-po-box/adapter.js +3 -3
- package/out/src/adapters/synth-po-box/adapter.js.map +1 -1
- package/out/src/adapters/tiger/adapter.d.ts +1 -1
- package/out/src/adapters/tiger/adapter.d.ts.map +1 -1
- package/out/src/adapters/tiger/adapter.js +2 -2
- package/out/src/adapters/tiger/adapter.js.map +1 -1
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.js +7 -6
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.js.map +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.js +11 -7
- package/out/src/adapters/usgov-imls-pls/adapter.js.map +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.js +6 -5
- package/out/src/adapters/usgov-irs-bmf/adapter.js.map +1 -1
- package/out/src/adapters/usgov-nad/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-nad/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-nad/adapter.js +8 -8
- package/out/src/adapters/usgov-nad/adapter.js.map +1 -1
- package/out/src/adapters/usgov-nppes/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-nppes/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-nppes/adapter.js +10 -10
- package/out/src/adapters/usgov-nppes/adapter.js.map +1 -1
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js +7 -6
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js.map +1 -1
- package/out/src/{adapter.d.ts → adapters/utils/index.d.ts} +8 -2
- package/out/src/adapters/utils/index.d.ts.map +1 -0
- package/out/src/{adapter.js → adapters/utils/index.js} +11 -3
- package/out/src/adapters/utils/index.js.map +1 -0
- package/out/src/adapters/wof-admin-jp/adapter.d.ts +1 -1
- package/out/src/adapters/wof-admin-jp/adapter.d.ts.map +1 -1
- package/out/src/adapters/wof-admin-jp/adapter.js +5 -5
- package/out/src/adapters/wof-admin-jp/adapter.js.map +1 -1
- package/out/src/adapters/wof-admin-json/adapter.d.ts +4 -15
- package/out/src/adapters/wof-admin-json/adapter.d.ts.map +1 -1
- package/out/src/adapters/wof-admin-json/adapter.js +11 -35
- package/out/src/adapters/wof-admin-json/adapter.js.map +1 -1
- package/out/src/adapters/wof-json-rows.d.ts +32 -0
- package/out/src/adapters/wof-json-rows.d.ts.map +1 -0
- package/out/src/adapters/wof-json-rows.js +45 -0
- package/out/src/adapters/wof-json-rows.js.map +1 -0
- package/out/src/adapters/wof-postalcode-json/adapter.d.ts +4 -9
- package/out/src/adapters/wof-postalcode-json/adapter.d.ts.map +1 -1
- package/out/src/adapters/wof-postalcode-json/adapter.js +12 -37
- package/out/src/adapters/wof-postalcode-json/adapter.js.map +1 -1
- package/out/src/build.d.ts +4 -4
- package/out/src/build.d.ts.map +1 -1
- package/out/src/build.js +7 -7
- package/out/src/build.js.map +1 -1
- package/out/src/index.d.ts +3 -17
- package/out/src/index.d.ts.map +1 -1
- package/out/src/index.js +3 -17
- package/out/src/index.js.map +1 -1
- package/out/src/name-prone-us-suffixes.d.ts +12 -0
- package/out/src/name-prone-us-suffixes.d.ts.map +1 -0
- package/out/src/name-prone-us-suffixes.js +12 -0
- package/out/src/name-prone-us-suffixes.js.map +1 -0
- package/out/src/parquet-wrapper/reader.d.ts.map +1 -1
- package/out/src/parquet-wrapper/reader.js +5 -0
- package/out/src/parquet-wrapper/reader.js.map +1 -1
- package/out/src/runner.d.ts +2 -2
- package/out/src/runner.d.ts.map +1 -1
- package/out/src/runner.js +1 -1
- package/out/src/runner.js.map +1 -1
- package/out/src/shard-recipes/anchor-absorption.d.ts.map +1 -1
- package/out/src/shard-recipes/anchor-absorption.js +4 -5
- package/out/src/shard-recipes/anchor-absorption.js.map +1 -1
- package/out/src/shard-recipes/bare-country.d.ts +25 -0
- package/out/src/shard-recipes/bare-country.d.ts.map +1 -0
- package/out/src/shard-recipes/bare-country.js +87 -0
- package/out/src/shard-recipes/bare-country.js.map +1 -0
- package/out/src/shard-recipes/boundary-stress.d.ts.map +1 -1
- package/out/src/shard-recipes/boundary-stress.js +2 -2
- package/out/src/shard-recipes/boundary-stress.js.map +1 -1
- package/out/src/shard-recipes/country-balanced.d.ts.map +1 -1
- package/out/src/shard-recipes/country-balanced.js +14 -21
- package/out/src/shard-recipes/country-balanced.js.map +1 -1
- package/out/src/shard-recipes/cz-pcfirst-preposition.d.ts.map +1 -1
- package/out/src/shard-recipes/cz-pcfirst-preposition.js +28 -10
- package/out/src/shard-recipes/cz-pcfirst-preposition.js.map +1 -1
- package/out/src/shard-recipes/fr-admin-split.d.ts.map +1 -1
- package/out/src/shard-recipes/fr-admin-split.js +4 -3
- package/out/src/shard-recipes/fr-admin-split.js.map +1 -1
- package/out/src/shard-recipes/fr-bare-street.d.ts.map +1 -1
- package/out/src/shard-recipes/fr-bare-street.js +72 -11
- package/out/src/shard-recipes/fr-bare-street.js.map +1 -1
- package/out/src/shard-recipes/fr-lieudit.d.ts.map +1 -1
- package/out/src/shard-recipes/fr-lieudit.js +4 -3
- package/out/src/shard-recipes/fr-lieudit.js.map +1 -1
- package/out/src/shard-recipes/fr-order.d.ts.map +1 -1
- package/out/src/shard-recipes/fr-order.js +11 -20
- package/out/src/shard-recipes/fr-order.js.map +1 -1
- package/out/src/shard-recipes/german.d.ts.map +1 -1
- package/out/src/shard-recipes/german.js +8 -14
- package/out/src/shard-recipes/german.js.map +1 -1
- package/out/src/shard-recipes/house-venue.d.ts.map +1 -1
- package/out/src/shard-recipes/house-venue.js +1 -1
- package/out/src/shard-recipes/house-venue.js.map +1 -1
- package/out/src/shard-recipes/index.d.ts.map +1 -1
- package/out/src/shard-recipes/index.js +8 -1
- package/out/src/shard-recipes/index.js.map +1 -1
- package/out/src/shard-recipes/intersection.d.ts.map +1 -1
- package/out/src/shard-recipes/intersection.js +7 -13
- package/out/src/shard-recipes/intersection.js.map +1 -1
- package/out/src/shard-recipes/locale.d.ts +5 -5
- package/out/src/shard-recipes/locale.d.ts.map +1 -1
- package/out/src/shard-recipes/locale.js +13 -20
- package/out/src/shard-recipes/locale.js.map +1 -1
- package/out/src/shard-recipes/no-street.d.ts.map +1 -1
- package/out/src/shard-recipes/no-street.js +1 -1
- package/out/src/shard-recipes/no-street.js.map +1 -1
- package/out/src/shard-recipes/po-box-cedex.d.ts.map +1 -1
- package/out/src/shard-recipes/po-box-cedex.js +60 -43
- package/out/src/shard-recipes/po-box-cedex.js.map +1 -1
- package/out/src/shard-recipes/po-box.d.ts.map +1 -1
- package/out/src/shard-recipes/po-box.js +1 -1
- package/out/src/shard-recipes/po-box.js.map +1 -1
- package/out/src/shard-recipes/reviewed-postcode-tail.d.ts +47 -0
- package/out/src/shard-recipes/reviewed-postcode-tail.d.ts.map +1 -0
- package/out/src/shard-recipes/reviewed-postcode-tail.js +125 -0
- package/out/src/shard-recipes/reviewed-postcode-tail.js.map +1 -0
- package/out/src/shard-recipes/scaffold.d.ts +51 -23
- package/out/src/shard-recipes/scaffold.d.ts.map +1 -1
- package/out/src/shard-recipes/scaffold.js +59 -23
- package/out/src/shard-recipes/scaffold.js.map +1 -1
- package/out/src/shard-recipes/street-affix.d.ts +54 -0
- package/out/src/shard-recipes/street-affix.d.ts.map +1 -1
- package/out/src/shard-recipes/street-affix.js +203 -35
- package/out/src/shard-recipes/street-affix.js.map +1 -1
- package/out/src/shard-recipes/street-bare.d.ts.map +1 -1
- package/out/src/shard-recipes/street-bare.js +3 -3
- package/out/src/shard-recipes/street-bare.js.map +1 -1
- package/out/src/shard-recipes/street.d.ts.map +1 -1
- package/out/src/shard-recipes/street.js +2 -2
- package/out/src/shard-recipes/street.js.map +1 -1
- package/out/src/shard-recipes/sub-venue-sources.d.ts +3 -6
- package/out/src/shard-recipes/sub-venue-sources.d.ts.map +1 -1
- package/out/src/shard-recipes/sub-venue-sources.js +4 -9
- package/out/src/shard-recipes/sub-venue-sources.js.map +1 -1
- package/out/src/shard-recipes/sub-venue.d.ts +2 -2
- package/out/src/shard-recipes/sub-venue.d.ts.map +1 -1
- package/out/src/shard-recipes/sub-venue.js +7 -6
- package/out/src/shard-recipes/sub-venue.js.map +1 -1
- package/out/src/shard-recipes/trailing-region.d.ts +74 -0
- package/out/src/shard-recipes/trailing-region.d.ts.map +1 -0
- package/out/src/shard-recipes/trailing-region.js +157 -0
- package/out/src/shard-recipes/trailing-region.js.map +1 -0
- package/out/src/shard-recipes/unit.d.ts.map +1 -1
- package/out/src/shard-recipes/unit.js +6 -12
- package/out/src/shard-recipes/unit.js.map +1 -1
- package/out/src/{synthesize-anchor-absorption.d.ts → synthesizers/anchor-absorption.d.ts} +1 -1
- package/out/src/synthesizers/anchor-absorption.d.ts.map +1 -0
- package/out/src/{synthesize-anchor-absorption.js → synthesizers/anchor-absorption.js} +1 -1
- package/out/src/synthesizers/anchor-absorption.js.map +1 -0
- package/out/src/{synthesize-boundary-stress.d.ts → synthesizers/boundary-stress.d.ts} +3 -3
- package/out/src/synthesizers/boundary-stress.d.ts.map +1 -0
- package/out/src/{synthesize-boundary-stress.js → synthesizers/boundary-stress.js} +2 -2
- package/out/src/synthesizers/boundary-stress.js.map +1 -0
- package/out/src/{synthesize-german.d.ts → synthesizers/german.d.ts} +2 -2
- package/out/src/synthesizers/german.d.ts.map +1 -0
- package/out/src/{synthesize-german.js → synthesizers/german.js} +2 -2
- package/out/src/synthesizers/german.js.map +1 -0
- package/out/src/{synthesize-house-venue.d.ts → synthesizers/house-venue.d.ts} +4 -4
- package/out/src/synthesizers/house-venue.d.ts.map +1 -0
- package/out/src/{synthesize-house-venue.js → synthesizers/house-venue.js} +20 -6
- package/out/src/synthesizers/house-venue.js.map +1 -0
- package/out/src/{synthesize-intersection.d.ts → synthesizers/intersection.d.ts} +2 -2
- package/out/src/synthesizers/intersection.d.ts.map +1 -0
- package/out/src/{synthesize-intersection.js → synthesizers/intersection.js} +1 -1
- package/out/src/synthesizers/intersection.js.map +1 -0
- package/out/src/{synthesize-no-street.d.ts → synthesizers/no-street.d.ts} +3 -3
- package/out/src/synthesizers/no-street.d.ts.map +1 -0
- package/out/src/{synthesize-no-street.js → synthesizers/no-street.js} +2 -2
- package/out/src/synthesizers/no-street.js.map +1 -0
- package/out/src/{synthesize-po-box.d.ts → synthesizers/po-box.d.ts} +2 -2
- package/out/src/synthesizers/po-box.d.ts.map +1 -0
- package/out/src/{synthesize-po-box.js → synthesizers/po-box.js} +1 -1
- package/out/src/synthesizers/po-box.js.map +1 -0
- package/out/src/{synthesize-street.d.ts → synthesizers/street.d.ts} +2 -2
- package/out/src/synthesizers/street.d.ts.map +1 -0
- package/out/src/{synthesize-street.js → synthesizers/street.js} +4 -3
- package/out/src/synthesizers/street.js.map +1 -0
- package/out/src/{synthesize.d.ts → synthesizers/utils.d.ts} +3 -3
- package/out/src/synthesizers/utils.d.ts.map +1 -0
- package/out/src/{synthesize.js → synthesizers/utils.js} +5 -4
- package/out/src/synthesizers/utils.js.map +1 -0
- package/out/src/tools/align-shard.d.ts.map +1 -1
- package/out/src/tools/align-shard.js +2 -2
- package/out/src/tools/align-shard.js.map +1 -1
- package/out/src/tools/fetch/ban.d.ts.map +1 -1
- package/out/src/tools/fetch/ban.js +2 -18
- package/out/src/tools/fetch/ban.js.map +1 -1
- package/out/src/tools/fetch/download.d.ts +12 -3
- package/out/src/tools/fetch/download.d.ts.map +1 -1
- package/out/src/tools/fetch/download.js +20 -4
- package/out/src/tools/fetch/download.js.map +1 -1
- package/out/src/tools/fetch/geonames-dump.d.ts +87 -0
- package/out/src/tools/fetch/geonames-dump.d.ts.map +1 -0
- package/out/src/tools/fetch/geonames-dump.js +178 -0
- package/out/src/tools/fetch/geonames-dump.js.map +1 -0
- package/out/src/tools/fetch/geonames-postal.d.ts +76 -0
- package/out/src/tools/fetch/geonames-postal.d.ts.map +1 -0
- package/out/src/tools/fetch/geonames-postal.js +125 -0
- package/out/src/tools/fetch/geonames-postal.js.map +1 -0
- package/out/src/tools/fetch/imls-pls.d.ts.map +1 -1
- package/out/src/tools/fetch/imls-pls.js +5 -17
- package/out/src/tools/fetch/imls-pls.js.map +1 -1
- package/out/src/tools/fetch/index.d.ts +11 -0
- package/out/src/tools/fetch/index.d.ts.map +1 -1
- package/out/src/tools/fetch/index.js +11 -0
- package/out/src/tools/fetch/index.js.map +1 -1
- package/out/src/tools/fetch/nad.d.ts.map +1 -1
- package/out/src/tools/fetch/nad.js +20 -11
- package/out/src/tools/fetch/nad.js.map +1 -1
- package/out/src/tools/fetch/nppes.d.ts.map +1 -1
- package/out/src/tools/fetch/nppes.js +17 -22
- package/out/src/tools/fetch/nppes.js.map +1 -1
- package/out/src/tools/fetch/openaddresses.d.ts.map +1 -1
- package/out/src/tools/fetch/openaddresses.js +18 -17
- package/out/src/tools/fetch/openaddresses.js.map +1 -1
- package/out/src/tools/fetch/ourairports.d.ts.map +1 -1
- package/out/src/tools/fetch/ourairports.js +7 -2
- package/out/src/tools/fetch/ourairports.js.map +1 -1
- package/out/src/tools/fetch/ppd.d.ts +0 -4
- package/out/src/tools/fetch/ppd.d.ts.map +1 -1
- package/out/src/tools/fetch/ppd.js +1 -1
- package/out/src/tools/fetch/ppd.js.map +1 -1
- package/out/src/tools/fetch/state-hi-schools.d.ts.map +1 -1
- package/out/src/tools/fetch/state-hi-schools.js +3 -19
- package/out/src/tools/fetch/state-hi-schools.js.map +1 -1
- package/out/src/tools/fetch/state-sources.d.ts +4 -0
- package/out/src/tools/fetch/state-sources.d.ts.map +1 -1
- package/out/src/tools/fetch/state-sources.js +1 -5
- package/out/src/tools/fetch/state-sources.js.map +1 -1
- package/out/src/tools/fetch/tiger-full.d.ts.map +1 -1
- package/out/src/tools/fetch/tiger-full.js +15 -21
- package/out/src/tools/fetch/tiger-full.js.map +1 -1
- package/out/src/tools/golden-expand.d.ts.map +1 -1
- package/out/src/tools/golden-expand.js +34 -25
- package/out/src/tools/golden-expand.js.map +1 -1
- package/out/src/tools/golden-relabel-street.d.ts.map +1 -1
- package/out/src/tools/golden-relabel-street.js +4 -77
- package/out/src/tools/golden-relabel-street.js.map +1 -1
- package/out/src/tools/index.d.ts +2 -2
- package/out/src/tools/index.d.ts.map +1 -1
- package/out/src/tools/index.js +2 -2
- package/out/src/tools/index.js.map +1 -1
- package/out/src/tools/ingest-csv.d.ts.map +1 -1
- package/out/src/tools/ingest-csv.js +0 -11
- package/out/src/tools/ingest-csv.js.map +1 -1
- package/out/src/tools/overlay-manifest.d.ts +4 -0
- package/out/src/tools/overlay-manifest.d.ts.map +1 -1
- package/out/src/tools/overlay-manifest.js +16 -6
- package/out/src/tools/overlay-manifest.js.map +1 -1
- package/out/src/tools/postcode-triples.d.ts +175 -0
- package/out/src/tools/postcode-triples.d.ts.map +1 -0
- package/out/src/tools/postcode-triples.js +304 -0
- package/out/src/tools/postcode-triples.js.map +1 -0
- package/out/src/tools/shard-kryptonite.d.ts.map +1 -1
- package/out/src/tools/shard-kryptonite.js +1 -3
- package/out/src/tools/shard-kryptonite.js.map +1 -1
- package/out/src/tools/shard-translit.d.ts.map +1 -1
- package/out/src/tools/shard-translit.js +4 -27
- package/out/src/tools/shard-translit.js.map +1 -1
- package/out/src/tools/sub-venue/harvest.d.ts +100 -0
- package/out/src/tools/sub-venue/harvest.d.ts.map +1 -0
- package/out/src/tools/sub-venue/harvest.js +168 -0
- package/out/src/tools/sub-venue/harvest.js.map +1 -0
- package/out/src/tools/sub-venue/head-nouns.d.ts +50 -0
- package/out/src/tools/sub-venue/head-nouns.d.ts.map +1 -0
- package/out/src/tools/sub-venue/head-nouns.js +210 -0
- package/out/src/tools/sub-venue/head-nouns.js.map +1 -0
- package/out/src/tools/sub-venue/surfaces.d.ts +45 -0
- package/out/src/tools/sub-venue/surfaces.d.ts.map +1 -0
- package/out/src/tools/sub-venue/surfaces.js +77 -0
- package/out/src/tools/sub-venue/surfaces.js.map +1 -0
- package/out/src/tools/sub-venue/table.d.ts +229 -0
- package/out/src/tools/sub-venue/table.d.ts.map +1 -0
- package/out/src/tools/sub-venue/table.js +108 -0
- package/out/src/tools/sub-venue/table.js.map +1 -0
- package/out/src/tools/sub-venue/wikidata.d.ts +26 -0
- package/out/src/tools/sub-venue/wikidata.d.ts.map +1 -0
- package/out/src/tools/sub-venue/wikidata.js +62 -0
- package/out/src/tools/sub-venue/wikidata.js.map +1 -0
- package/out/src/tools/sub-venue-lexicon.d.ts +27 -378
- package/out/src/tools/sub-venue-lexicon.d.ts.map +1 -1
- package/out/src/tools/sub-venue-lexicon.js +30 -565
- package/out/src/tools/sub-venue-lexicon.js.map +1 -1
- package/out/src/{align.d.ts → utils/align.d.ts} +1 -1
- package/out/src/utils/align.d.ts.map +1 -0
- package/out/src/utils/align.js.map +1 -0
- package/out/src/utils/golden.d.ts.map +1 -0
- package/out/src/{golden.js → utils/golden.js} +2 -2
- package/out/src/utils/golden.js.map +1 -0
- package/out/src/utils/index.d.ts +14 -0
- package/out/src/utils/index.d.ts.map +1 -0
- package/out/src/utils/index.js +14 -0
- package/out/src/utils/index.js.map +1 -0
- package/out/src/utils/license.d.ts.map +1 -0
- package/out/src/{license.js → utils/license.js} +1 -1
- package/out/src/utils/license.js.map +1 -0
- package/out/src/{parquet.d.ts → utils/parquet.d.ts} +24 -5
- package/out/src/utils/parquet.d.ts.map +1 -0
- package/out/src/{parquet.js → utils/parquet.js} +6 -3
- package/out/src/utils/parquet.js.map +1 -0
- package/out/src/{split.d.ts → utils/split.d.ts} +1 -1
- package/out/src/utils/split.d.ts.map +1 -0
- package/out/src/{split.js → utils/split.js} +2 -2
- package/out/src/utils/split.js.map +1 -0
- package/out/src/utils/tokenize.d.ts.map +1 -0
- package/out/src/utils/tokenize.js.map +1 -0
- package/out/src/utils/wof-json.d.ts.map +1 -0
- package/out/src/utils/wof-json.js.map +1 -0
- package/package.json +287 -21
- package/src/adapters/ban/adapter.ts +7 -5
- package/src/adapters/fcc-bdc/adapter.ts +5 -4
- package/src/adapters/geonames/adapter.ts +3 -3
- package/src/adapters/geonames-postal/adapter.ts +4 -4
- package/src/adapters/gnaf/adapter.ts +3 -3
- package/src/adapters/gnaf/assemble.ts +1 -1
- package/src/adapters/index.ts +3 -2
- package/src/adapters/openaddresses/adapter.ts +4 -4
- package/src/adapters/overture/adapter.ts +3 -3
- package/src/adapters/state-hi-schools/adapter.ts +8 -7
- package/src/adapters/state-ia-contractors/adapter.ts +13 -8
- package/src/adapters/state-ny-notaries/adapter.ts +13 -32
- package/src/adapters/state-tx-notaries/adapter.ts +13 -8
- package/src/adapters/synth-po-box/adapter.ts +4 -4
- package/src/adapters/tiger/adapter.ts +5 -3
- package/src/adapters/usgov-hrsa-fqhc/adapter.ts +8 -7
- package/src/adapters/usgov-imls-pls/adapter.ts +12 -8
- package/src/adapters/usgov-irs-bmf/adapter.ts +7 -6
- package/src/adapters/usgov-nad/adapter.ts +9 -9
- package/src/adapters/usgov-nppes/adapter.ts +13 -12
- package/src/adapters/usgov-samhsa-treatment-locator/adapter.ts +8 -7
- package/src/{adapter.ts → adapters/utils/index.ts} +15 -3
- package/src/adapters/wof-admin-jp/adapter.ts +9 -12
- package/src/adapters/wof-admin-json/adapter.ts +15 -54
- package/src/adapters/wof-json-rows.ts +79 -0
- package/src/adapters/wof-postalcode-json/adapter.ts +16 -50
- package/src/build.ts +8 -8
- package/src/index.ts +3 -17
- package/src/name-prone-us-suffixes.ts +12 -0
- package/src/parquet-wrapper/reader.ts +9 -0
- package/src/runner.ts +2 -2
- package/src/shard-recipes/anchor-absorption.ts +5 -5
- package/src/shard-recipes/bare-country.ts +95 -0
- package/src/shard-recipes/boundary-stress.ts +3 -2
- package/src/shard-recipes/country-balanced.ts +16 -27
- package/src/shard-recipes/cz-pcfirst-preposition.ts +29 -10
- package/src/shard-recipes/fr-admin-split.ts +6 -4
- package/src/shard-recipes/fr-bare-street.ts +85 -10
- package/src/shard-recipes/fr-lieudit.ts +6 -4
- package/src/shard-recipes/fr-order.ts +13 -26
- package/src/shard-recipes/german.ts +9 -18
- package/src/shard-recipes/house-venue.ts +2 -1
- package/src/shard-recipes/index.ts +8 -1
- package/src/shard-recipes/intersection.ts +9 -17
- package/src/shard-recipes/locale.ts +16 -24
- package/src/shard-recipes/no-street.ts +2 -1
- package/src/shard-recipes/po-box-cedex.ts +76 -58
- package/src/shard-recipes/po-box.ts +2 -1
- package/src/shard-recipes/reviewed-postcode-tail.ts +189 -0
- package/src/shard-recipes/scaffold.ts +99 -24
- package/src/shard-recipes/street-affix.ts +284 -45
- package/src/shard-recipes/street-bare.ts +4 -3
- package/src/shard-recipes/street.ts +3 -2
- package/src/shard-recipes/sub-venue-sources.ts +13 -23
- package/src/shard-recipes/sub-venue.ts +11 -9
- package/src/shard-recipes/trailing-region.ts +183 -0
- package/src/shard-recipes/unit.ts +8 -17
- package/src/{synthesize-boundary-stress.ts → synthesizers/boundary-stress.ts} +2 -2
- package/src/{synthesize-german.ts → synthesizers/german.ts} +3 -2
- package/src/{synthesize-house-venue.ts → synthesizers/house-venue.ts} +20 -6
- package/src/{synthesize-intersection.ts → synthesizers/intersection.ts} +1 -1
- package/src/{synthesize-no-street.ts → synthesizers/no-street.ts} +2 -2
- package/src/{synthesize-po-box.ts → synthesizers/po-box.ts} +1 -1
- package/src/{synthesize-street.ts → synthesizers/street.ts} +5 -3
- package/src/{synthesize.ts → synthesizers/utils.ts} +6 -4
- package/src/tools/align-shard.ts +3 -2
- package/src/tools/fetch/ban.ts +2 -22
- package/src/tools/fetch/download.ts +22 -4
- package/src/tools/fetch/geonames-dump.ts +267 -0
- package/src/tools/fetch/geonames-postal.ts +180 -0
- package/src/tools/fetch/imls-pls.ts +6 -20
- package/src/tools/fetch/index.ts +11 -0
- package/src/tools/fetch/nad.ts +21 -10
- package/src/tools/fetch/nppes.ts +17 -23
- package/src/tools/fetch/openaddresses.ts +18 -22
- package/src/tools/fetch/ourairports.ts +7 -2
- package/src/tools/fetch/ppd.ts +1 -1
- package/src/tools/fetch/state-hi-schools.ts +3 -23
- package/src/tools/fetch/state-sources.ts +1 -1
- package/src/tools/fetch/tiger-full.ts +17 -24
- package/src/tools/golden-expand.ts +44 -33
- package/src/tools/golden-relabel-street.ts +5 -68
- package/src/tools/index.ts +2 -2
- package/src/tools/ingest-csv.ts +0 -13
- package/src/tools/overlay-manifest.ts +20 -8
- package/src/tools/postcode-triples.ts +375 -0
- package/src/tools/shard-kryptonite.ts +4 -5
- package/src/tools/shard-translit.ts +16 -35
- package/src/tools/sub-venue/harvest.ts +235 -0
- package/src/tools/sub-venue/head-nouns.ts +242 -0
- package/src/tools/sub-venue/surfaces.ts +95 -0
- package/src/tools/sub-venue/table.ts +281 -0
- package/src/tools/sub-venue/wikidata.ts +85 -0
- package/src/tools/sub-venue-lexicon.ts +67 -886
- package/src/{align.ts → utils/align.ts} +2 -1
- package/src/{golden.ts → utils/golden.ts} +2 -3
- package/src/utils/index.ts +14 -0
- package/src/{license.ts → utils/license.ts} +1 -1
- package/src/{parquet.ts → utils/parquet.ts} +22 -9
- package/src/{split.ts → utils/split.ts} +3 -3
- package/out/src/adapter.d.ts.map +0 -1
- package/out/src/adapter.js.map +0 -1
- package/out/src/align.d.ts.map +0 -1
- package/out/src/align.js.map +0 -1
- package/out/src/format.d.ts +0 -14
- package/out/src/format.d.ts.map +0 -1
- package/out/src/format.js +0 -14
- package/out/src/format.js.map +0 -1
- package/out/src/golden.d.ts.map +0 -1
- package/out/src/golden.js.map +0 -1
- package/out/src/license.d.ts.map +0 -1
- package/out/src/license.js.map +0 -1
- package/out/src/parquet.d.ts.map +0 -1
- package/out/src/parquet.js.map +0 -1
- package/out/src/split.d.ts.map +0 -1
- package/out/src/split.js.map +0 -1
- package/out/src/synthesize-anchor-absorption.d.ts.map +0 -1
- package/out/src/synthesize-anchor-absorption.js.map +0 -1
- package/out/src/synthesize-boundary-stress.d.ts.map +0 -1
- package/out/src/synthesize-boundary-stress.js.map +0 -1
- package/out/src/synthesize-german.d.ts.map +0 -1
- package/out/src/synthesize-german.js.map +0 -1
- package/out/src/synthesize-house-venue.d.ts.map +0 -1
- package/out/src/synthesize-house-venue.js.map +0 -1
- package/out/src/synthesize-intersection.d.ts.map +0 -1
- package/out/src/synthesize-intersection.js.map +0 -1
- package/out/src/synthesize-no-street.d.ts.map +0 -1
- package/out/src/synthesize-no-street.js.map +0 -1
- package/out/src/synthesize-po-box.d.ts.map +0 -1
- package/out/src/synthesize-po-box.js.map +0 -1
- package/out/src/synthesize-street.d.ts.map +0 -1
- package/out/src/synthesize-street.js.map +0 -1
- package/out/src/synthesize.d.ts.map +0 -1
- package/out/src/synthesize.js.map +0 -1
- package/out/src/tokenize.d.ts.map +0 -1
- package/out/src/tokenize.js.map +0 -1
- package/out/src/wof-json.d.ts.map +0 -1
- package/out/src/wof-json.js.map +0 -1
- package/src/format.ts +0 -14
- /package/out/src/{align.js → utils/align.js} +0 -0
- /package/out/src/{golden.d.ts → utils/golden.d.ts} +0 -0
- /package/out/src/{license.d.ts → utils/license.d.ts} +0 -0
- /package/out/src/{tokenize.d.ts → utils/tokenize.d.ts} +0 -0
- /package/out/src/{tokenize.js → utils/tokenize.js} +0 -0
- /package/out/src/{wof-json.d.ts → utils/wof-json.d.ts} +0 -0
- /package/out/src/{wof-json.js → utils/wof-json.js} +0 -0
- /package/src/{synthesize-anchor-absorption.ts → synthesizers/anchor-absorption.ts} +0 -0
- /package/src/{tokenize.ts → utils/tokenize.ts} +0 -0
- /package/src/{wof-json.ts → utils/wof-json.ts} +0 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* @file The harvest side of the sub-venue lexicon: what one row of a harvestable source looks like,
|
|
7
|
+
* how a file of them is read back, and what a pass over them extracts — attested surfaces plus the
|
|
8
|
+
* measured shape of each designator's identifier half.
|
|
9
|
+
*
|
|
10
|
+
* {@link SubVenueHarvestRow} is SOURCE-NEUTRAL, and verified so: an Overture Places row from the
|
|
11
|
+
* `airport_terminal` category is `{ designatorID, name }` and fits unchanged. It is declared here
|
|
12
|
+
* rather than imported so the builder does not take a dependency on `@mailwoman/osm` (which
|
|
13
|
+
* `@mailwoman/corpus` does not depend on) just to name a shape it reads from a file.
|
|
14
|
+
*
|
|
15
|
+
* Two measurements shape {@link extractAttestedPhrases}, and both are the reason it is safe to run
|
|
16
|
+
* over raw OSM at all:
|
|
17
|
+
*
|
|
18
|
+
* **A feature's `name` is usually the VENUE's name, not a sub-venue phrase.** On the Berlin extract
|
|
19
|
+
* (2,060 matched features) a `railway=platform` is named `Stendaler Straße` and an `amenity=university`
|
|
20
|
+
* is named `Hertie School`; across 250,116 named Great Britain features only 6,003 (2.40%) contain a
|
|
21
|
+
* designator token at all. So names are not harvested wholesale — a name contributes only when it
|
|
22
|
+
* CONTAINS a phrase already in the surface index, which is what makes `Terminal E (Untere Ebene)`
|
|
23
|
+
* evidence and `Otto Lilienthal Flughafen Berlin Tegel` not.
|
|
24
|
+
*
|
|
25
|
+
* **A matched phrase belongs to the record the PHRASE names, not the record the ROW carries.**
|
|
26
|
+
* Attributing every hit to `row.designatorID` — the rule that matched the FEATURE — produced `west →
|
|
27
|
+
* platform`, `hall → platform` and `biggin → platform` on the GB extract, because a bus stop tagged
|
|
28
|
+
* `public_transport=platform` is named "Village Hall" or "West Kensington"; 108 of 133 OSM-derived
|
|
29
|
+
* surfaces named a different record than the one they pointed at. Attribution therefore runs through
|
|
30
|
+
* the index, and the row's own designator is kept as `context` — exactly the axis a confound board
|
|
31
|
+
* needs, since a `hall` seen on a platform is a confound and a `hall` seen on a terminal is evidence.
|
|
32
|
+
*/
|
|
33
|
+
import { readFileSync } from "node:fs";
|
|
34
|
+
import { parseJSONStrict } from "@mailwoman/core/objects";
|
|
35
|
+
import { TextSpliterator } from "spliterator";
|
|
36
|
+
import { nameContainsSurfaces } from "./surfaces.js";
|
|
37
|
+
/**
|
|
38
|
+
* Classify an OSM `ref` into an {@link IdentifierShape} class.
|
|
39
|
+
*
|
|
40
|
+
* The classes are the ones Berlin's gates actually produced, plus the two aviation forms the corpus task names
|
|
41
|
+
* (`Terminal 2F` is digit-letter, `Concourse B` is letter). `range` covers both separators OSM uses for a gate serving
|
|
42
|
+
* more than one stand: `16-18` and `0/1`.
|
|
43
|
+
*/
|
|
44
|
+
export function classifyIdentifier(ref) {
|
|
45
|
+
const value = ref.trim();
|
|
46
|
+
if (/^[0-9]+$/.test(value))
|
|
47
|
+
return "digit";
|
|
48
|
+
if (/^[A-Za-z]$/.test(value))
|
|
49
|
+
return "letter";
|
|
50
|
+
if (/^[A-Za-z]+[0-9]+$/.test(value))
|
|
51
|
+
return "letter-digit";
|
|
52
|
+
if (/^[0-9]+[A-Za-z]+$/.test(value))
|
|
53
|
+
return "digit-letter";
|
|
54
|
+
if (/^[0-9A-Za-z]+\s*[-/]\s*[0-9A-Za-z]+$/.test(value))
|
|
55
|
+
return "range";
|
|
56
|
+
return "other";
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* How many real `ref` values each {@link IdentifierShape} keeps.
|
|
60
|
+
*
|
|
61
|
+
* Eight, not "all" and not one. The field exists so a shard author can see what a class actually CONTAINS — GB's
|
|
62
|
+
* `other` class turned out to be semicolon multi-values (`1;2;3`, `13;14`), which one example would have hidden and
|
|
63
|
+
* which the class name does not say. Eight fits a terminal line and covers the variety inside every class the GB
|
|
64
|
+
* extract produced. The COUNT lives in `observations`; this is a sample, not a census.
|
|
65
|
+
*/
|
|
66
|
+
const IDENTIFIER_EXAMPLES_PER_SHAPE = 8;
|
|
67
|
+
/**
|
|
68
|
+
* Harvest attested phrases and identifier shapes out of a source's rows.
|
|
69
|
+
*
|
|
70
|
+
* `index` gates the name harvest — a name contributes only when it CONTAINS a phrase already in the table. That filter
|
|
71
|
+
* is the whole reason this function is safe to run over raw OSM: see this file's header for the Berlin measurement that
|
|
72
|
+
* motivated it. The index also decides ATTRIBUTION: a hit is a surface of the record the PHRASE names, and the row's
|
|
73
|
+
* own designator is recorded as `context`.
|
|
74
|
+
*
|
|
75
|
+
* Returns surfaces with real `observations` counts, so the lexicon can rank `terminal` above a phrase attested once.
|
|
76
|
+
*/
|
|
77
|
+
export function extractAttestedPhrases(rows, index, options = {}) {
|
|
78
|
+
const source = options.source ?? "osm";
|
|
79
|
+
const region = options.region ?? "";
|
|
80
|
+
/**
|
|
81
|
+
* `phrase\0lang\0source` → { count, context }.
|
|
82
|
+
*/
|
|
83
|
+
const surfaceCounts = new Map();
|
|
84
|
+
/**
|
|
85
|
+
* `designatorID\0shape` → { count, examples }.
|
|
86
|
+
*/
|
|
87
|
+
const shapes = new Map();
|
|
88
|
+
const note = (phrase, lang, sourceTag, context) => {
|
|
89
|
+
const key = `${phrase}\0${lang}\0${sourceTag}`;
|
|
90
|
+
const entry = surfaceCounts.get(key) ?? { count: 0, context: new Map() };
|
|
91
|
+
entry.count++;
|
|
92
|
+
entry.context.set(context, (entry.context.get(context) ?? 0) + 1);
|
|
93
|
+
surfaceCounts.set(key, entry);
|
|
94
|
+
};
|
|
95
|
+
for (const row of rows) {
|
|
96
|
+
if (row.name) {
|
|
97
|
+
for (const hit of nameContainsSurfaces(row.name, index)) {
|
|
98
|
+
// `und` — the default `name` tag carries no language. Overture's `name` is the same: a
|
|
99
|
+
// primary name in whatever language the place uses, untagged.
|
|
100
|
+
note(hit, "und", `${source}:name`, row.designatorID);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
for (const [lang, localized] of Object.entries(row.localizedNames ?? {})) {
|
|
104
|
+
for (const hit of nameContainsSurfaces(localized, index)) {
|
|
105
|
+
note(hit, lang, `${source}:name:${lang}`, row.designatorID);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (row.ref) {
|
|
109
|
+
const shape = classifyIdentifier(row.ref);
|
|
110
|
+
const key = `${row.designatorID}\0${shape}`;
|
|
111
|
+
const entry = shapes.get(key) ?? { count: 0, examples: new Set() };
|
|
112
|
+
entry.count++;
|
|
113
|
+
if (entry.examples.size < IDENTIFIER_EXAMPLES_PER_SHAPE) {
|
|
114
|
+
entry.examples.add(row.ref.trim());
|
|
115
|
+
}
|
|
116
|
+
shapes.set(key, entry);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const surfaces = [...surfaceCounts].map(([key, entry]) => {
|
|
120
|
+
const [phrase, lang, sourceTag] = key.split("\0");
|
|
121
|
+
const record = index.get(phrase);
|
|
122
|
+
return {
|
|
123
|
+
phrase,
|
|
124
|
+
recordID: record.recordID,
|
|
125
|
+
recordKind: record.recordKind,
|
|
126
|
+
lang,
|
|
127
|
+
region,
|
|
128
|
+
source: sourceTag,
|
|
129
|
+
curated: false,
|
|
130
|
+
observations: entry.count,
|
|
131
|
+
context: Object.fromEntries([...entry.context].toSorted((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))),
|
|
132
|
+
};
|
|
133
|
+
});
|
|
134
|
+
const identifierShapes = [...shapes].map(([key, entry]) => {
|
|
135
|
+
const [designatorID, shape] = key.split("\0");
|
|
136
|
+
return {
|
|
137
|
+
designatorID,
|
|
138
|
+
region,
|
|
139
|
+
shape,
|
|
140
|
+
observations: entry.count,
|
|
141
|
+
examples: [...entry.examples].toSorted((a, b) => a.localeCompare(b)),
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
return { surfaces, identifierShapes };
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Read a JSONL file of {@link SubVenueHarvestRow}s. Blank lines and unparseable rows are skipped rather than fatal — an
|
|
148
|
+
* extract is a build output, and one malformed line should not cost the whole lexicon.
|
|
149
|
+
*/
|
|
150
|
+
export function readSubVenueJSONL(path) {
|
|
151
|
+
const out = [];
|
|
152
|
+
// `TextSpliterator` rather than `split("\n")` — a whole-country extract runs to 250,000 lines
|
|
153
|
+
// (52 MB for Great Britain), and materializing every segment before reading the first is exactly
|
|
154
|
+
// what the repo lint rule exists to prevent.
|
|
155
|
+
for (const line of TextSpliterator.from(readFileSync(path, "utf8"))) {
|
|
156
|
+
const trimmed = line.trim();
|
|
157
|
+
if (!trimmed)
|
|
158
|
+
continue;
|
|
159
|
+
try {
|
|
160
|
+
out.push(parseJSONStrict(trimmed));
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return out;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=harvest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvest.js","sourceRoot":"","sources":["../../../../src/tools/sub-venue/harvest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* @file Head-noun derivation for the sub-venue lexicon — proposing the ADDRESSED form of a designator
|
|
7
|
+
* from the encyclopaedic label a vocabulary source carries.
|
|
8
|
+
*
|
|
9
|
+
* Wikidata's label for a concept is the encyclopaedic name (`terminal aeroportuaria`, `letištní
|
|
10
|
+
* terminál`, `havalimanı terminali`), while the addressed form is the bare head (`Terminal`,
|
|
11
|
+
* `Terminál`, `Terminali`). Nothing can promote the encyclopaedic form, so the head has to be
|
|
12
|
+
* extracted before the curation pass has anything to decide about — that gap is why the first wave of
|
|
13
|
+
* this table shipped 1,014 uncurated surfaces.
|
|
14
|
+
*
|
|
15
|
+
* Everything derived lands `curated: false`. A derivation is a HYPOTHESIS about what the addressed
|
|
16
|
+
* form is; a locale's own data is what confirms or kills it.
|
|
17
|
+
*/
|
|
18
|
+
import type { SubVenueSurface } from "./table.ts";
|
|
19
|
+
/**
|
|
20
|
+
* Derive the HEAD NOUN of every multi-part surface, so `terminal aeroportuaria` contributes the form anyone actually
|
|
21
|
+
* writes on an envelope.
|
|
22
|
+
*
|
|
23
|
+
* The problem this solves is the whole reason wave 1 shipped 1,014 uncurated surfaces: Wikidata's label for a concept
|
|
24
|
+
* is the ENCYCLOPAEDIC name (`terminal aeroportuaria`, `letištní terminál`, `havalimanı terminali`), while the
|
|
25
|
+
* addressed form is the bare head (`Terminal`, `Terminál`, `Terminali`). Nothing can promote the encyclopaedic form, so
|
|
26
|
+
* the head has to be extracted before the curation pass has anything to decide about.
|
|
27
|
+
*
|
|
28
|
+
* Two derivations, because the table holds two kinds of writing:
|
|
29
|
+
*
|
|
30
|
+
* - **Latin script — the COGNATE test.** A token is the head when its ASCII fold shares {@link HEAD_NOUN_PREFIX_FLOOR}
|
|
31
|
+
* leading characters with the designator's own canonical id. Nothing subtler survived contact with the data: an
|
|
32
|
+
* earlier version matched a token against any SINGLE-TOKEN surface of the record, and because Dutch `universiteit` is
|
|
33
|
+
* a one-token surface of `campus`, it derived `universitario`, `universitaire`, `üniversite` and twenty more as head
|
|
34
|
+
* nouns of `campus`. Those are the MODIFIER half of the label, and admitting them would have taught the harvest to
|
|
35
|
+
* read "Ciudad Universitaria" as sub-venue structure.
|
|
36
|
+
* - **Non-Latin script — the SHARED-SUBSTRING test.** The cognate test cannot reach a script the id is not written in,
|
|
37
|
+
* and for Han and Kana a token split finds nothing at all. So every substring of length ≥
|
|
38
|
+
* {@link NON_LATIN_HEAD_MIN_LENGTH} occurring in at least two DISTINCT surfaces of the same record and primary
|
|
39
|
+
* language becomes a candidate, ranked by how many surfaces carry it. Japanese yields `ターミナル` (in all five `ja`
|
|
40
|
+
* terminal labels) ahead of `ターミナルビル` (three); Chinese yields `航站`, `航站楼`, `航站樓`. Where the script DOES space its
|
|
41
|
+
* words (Korean, Greek, Cyrillic) a candidate must be a whole token, so `공항 터미널` ∩ `공항터미널` gives `터미널` and never a
|
|
42
|
+
* fragment.
|
|
43
|
+
*
|
|
44
|
+
* The non-Latin branch deliberately emits SEVERAL candidates instead of picking one. Choosing between `航站` and `航站楼`
|
|
45
|
+
* from Wikidata alone is guesswork; the Japan extract answers it by counting, and the promotion ledger records which
|
|
46
|
+
* count won. Everything derived lands `curated: false` — the derivation is a hypothesis about what the addressed form
|
|
47
|
+
* is, and a locale's own data is what confirms or kills it.
|
|
48
|
+
*/
|
|
49
|
+
export declare function deriveHeadNounSurfaces(surfaces: readonly SubVenueSurface[]): SubVenueSurface[];
|
|
50
|
+
//# sourceMappingURL=head-nouns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"head-nouns.d.ts","sourceRoot":"","sources":["../../../../src/tools/sub-venue/head-nouns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAoDjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,eAAe,EAAE,CA+E9F"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* @file Head-noun derivation for the sub-venue lexicon — proposing the ADDRESSED form of a designator
|
|
7
|
+
* from the encyclopaedic label a vocabulary source carries.
|
|
8
|
+
*
|
|
9
|
+
* Wikidata's label for a concept is the encyclopaedic name (`terminal aeroportuaria`, `letištní
|
|
10
|
+
* terminál`, `havalimanı terminali`), while the addressed form is the bare head (`Terminal`,
|
|
11
|
+
* `Terminál`, `Terminali`). Nothing can promote the encyclopaedic form, so the head has to be
|
|
12
|
+
* extracted before the curation pass has anything to decide about — that gap is why the first wave of
|
|
13
|
+
* this table shipped 1,014 uncurated surfaces.
|
|
14
|
+
*
|
|
15
|
+
* Everything derived lands `curated: false`. A derivation is a HYPOTHESIS about what the addressed
|
|
16
|
+
* form is; a locale's own data is what confirms or kills it.
|
|
17
|
+
*/
|
|
18
|
+
import { isPresent } from "@mailwoman/core/objects";
|
|
19
|
+
/**
|
|
20
|
+
* Diacritic-flattened ASCII fold, for comparing a Slavic or Turkish inflection against its Latin root.
|
|
21
|
+
*/
|
|
22
|
+
function asciiFold(text) {
|
|
23
|
+
return text
|
|
24
|
+
.normalize("NFD")
|
|
25
|
+
.replaceAll(/\p{Diacritic}/gu, "")
|
|
26
|
+
.toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* How many leading characters two ASCII-folded forms must share for one to count as the other's inflection.
|
|
30
|
+
*
|
|
31
|
+
* Five, or the id's own length when that is shorter (`hall`, `gate`, `wing`, `pier` are four). Measured against the
|
|
32
|
+
* committed Wikidata pull: at five, `terminal`/`terminál`/`terminale`/`terminali`/`terminála`/`terminalo` are all
|
|
33
|
+
* accepted for `terminal` while `campo` and `campws` are both rejected for `campus` (they share four). At six the
|
|
34
|
+
* Spanish `satélite` is lost; at four, Italian `campo` is admitted and it means FIELD.
|
|
35
|
+
*/
|
|
36
|
+
const HEAD_NOUN_PREFIX_FLOOR = 5;
|
|
37
|
+
/**
|
|
38
|
+
* The shortest substring a non-Latin head-noun candidate may be. Two: `航站` and `터미널` are both real, `楼` alone is
|
|
39
|
+
* "building" and would fire on every Chinese building name.
|
|
40
|
+
*/
|
|
41
|
+
const NON_LATIN_HEAD_MIN_LENGTH = 2;
|
|
42
|
+
/**
|
|
43
|
+
* How many head-noun candidates one non-Latin record+language group may contribute. Six — enough to carry `ターミナル`,
|
|
44
|
+
* `ターミナルビル` and `旅客ターミナル` together, capped because the substring lattice of a nine-character label is large and, ranked
|
|
45
|
+
* by attesting-surface count, nothing past the sixth has more than the minimum two.
|
|
46
|
+
*/
|
|
47
|
+
const NON_LATIN_HEAD_CANDIDATE_CAP = 6;
|
|
48
|
+
/**
|
|
49
|
+
* Latin-script test — the scripts an ASCII-folded prefix comparison against a Latin designator id can work on.
|
|
50
|
+
*/
|
|
51
|
+
const LATIN_PHRASE = /^[\p{Script=Latin}\d\s\p{P}]+$/u;
|
|
52
|
+
/**
|
|
53
|
+
* The scripts the shared-substring derivation is allowed to run on: Han, Hiragana, Katakana, Hangul.
|
|
54
|
+
*
|
|
55
|
+
* NARROWER than "not Latin", and the narrowing was earned. Run over every non-Latin phrase in the table, the derivation
|
|
56
|
+
* produced 90 fragments of Cyrillic, Greek, Arabic, Thai, Burmese and Tamil words — `сгра`, `град`, `κτίρ`,
|
|
57
|
+
* `ิ่งก่อสร้า` — because those languages have exactly one surface per concept and the only substrings shared inside a
|
|
58
|
+
* group are pieces of one word. Every one of them was unusable, and none could ever be counted: `poi.db` is four
|
|
59
|
+
* countries and this wave's extracts are GB, DE, FR, ES and JP, so nothing in reach attests a Thai or Burmese surface.
|
|
60
|
+
* Deriving a candidate no available source can confirm is not a hypothesis, it is table weight.
|
|
61
|
+
*/
|
|
62
|
+
const SHARED_SUBSTRING_SCRIPT = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
|
|
63
|
+
/**
|
|
64
|
+
* Derive the HEAD NOUN of every multi-part surface, so `terminal aeroportuaria` contributes the form anyone actually
|
|
65
|
+
* writes on an envelope.
|
|
66
|
+
*
|
|
67
|
+
* The problem this solves is the whole reason wave 1 shipped 1,014 uncurated surfaces: Wikidata's label for a concept
|
|
68
|
+
* is the ENCYCLOPAEDIC name (`terminal aeroportuaria`, `letištní terminál`, `havalimanı terminali`), while the
|
|
69
|
+
* addressed form is the bare head (`Terminal`, `Terminál`, `Terminali`). Nothing can promote the encyclopaedic form, so
|
|
70
|
+
* the head has to be extracted before the curation pass has anything to decide about.
|
|
71
|
+
*
|
|
72
|
+
* Two derivations, because the table holds two kinds of writing:
|
|
73
|
+
*
|
|
74
|
+
* - **Latin script — the COGNATE test.** A token is the head when its ASCII fold shares {@link HEAD_NOUN_PREFIX_FLOOR}
|
|
75
|
+
* leading characters with the designator's own canonical id. Nothing subtler survived contact with the data: an
|
|
76
|
+
* earlier version matched a token against any SINGLE-TOKEN surface of the record, and because Dutch `universiteit` is
|
|
77
|
+
* a one-token surface of `campus`, it derived `universitario`, `universitaire`, `üniversite` and twenty more as head
|
|
78
|
+
* nouns of `campus`. Those are the MODIFIER half of the label, and admitting them would have taught the harvest to
|
|
79
|
+
* read "Ciudad Universitaria" as sub-venue structure.
|
|
80
|
+
* - **Non-Latin script — the SHARED-SUBSTRING test.** The cognate test cannot reach a script the id is not written in,
|
|
81
|
+
* and for Han and Kana a token split finds nothing at all. So every substring of length ≥
|
|
82
|
+
* {@link NON_LATIN_HEAD_MIN_LENGTH} occurring in at least two DISTINCT surfaces of the same record and primary
|
|
83
|
+
* language becomes a candidate, ranked by how many surfaces carry it. Japanese yields `ターミナル` (in all five `ja`
|
|
84
|
+
* terminal labels) ahead of `ターミナルビル` (three); Chinese yields `航站`, `航站楼`, `航站樓`. Where the script DOES space its
|
|
85
|
+
* words (Korean, Greek, Cyrillic) a candidate must be a whole token, so `공항 터미널` ∩ `공항터미널` gives `터미널` and never a
|
|
86
|
+
* fragment.
|
|
87
|
+
*
|
|
88
|
+
* The non-Latin branch deliberately emits SEVERAL candidates instead of picking one. Choosing between `航站` and `航站楼`
|
|
89
|
+
* from Wikidata alone is guesswork; the Japan extract answers it by counting, and the promotion ledger records which
|
|
90
|
+
* count won. Everything derived lands `curated: false` — the derivation is a hypothesis about what the addressed form
|
|
91
|
+
* is, and a locale's own data is what confirms or kills it.
|
|
92
|
+
*/
|
|
93
|
+
export function deriveHeadNounSurfaces(surfaces) {
|
|
94
|
+
const derived = new Map();
|
|
95
|
+
const seen = new Set(surfaces.map((s) => `${s.phrase}\0${s.recordID}\0${s.lang}`));
|
|
96
|
+
const emit = (phrase, from) => {
|
|
97
|
+
if (phrase === from.phrase)
|
|
98
|
+
return;
|
|
99
|
+
const key = `${phrase}\0${from.recordID}\0${from.lang}`;
|
|
100
|
+
if (seen.has(key) || derived.has(key))
|
|
101
|
+
return;
|
|
102
|
+
derived.set(key, {
|
|
103
|
+
phrase,
|
|
104
|
+
recordID: from.recordID,
|
|
105
|
+
recordKind: from.recordKind,
|
|
106
|
+
lang: from.lang,
|
|
107
|
+
region: "",
|
|
108
|
+
source: "derived:head-noun",
|
|
109
|
+
curated: false,
|
|
110
|
+
observations: 0,
|
|
111
|
+
context: {},
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
// ── Spacing scripts: prefix-match a token against a single-token surface of the same record ──────
|
|
115
|
+
// Latin script: a token that is a cognate of the designator's own canonical id.
|
|
116
|
+
for (const surface of surfaces) {
|
|
117
|
+
if (!LATIN_PHRASE.test(surface.phrase))
|
|
118
|
+
continue;
|
|
119
|
+
const parts = surface.phrase.split(/[^\p{L}\p{N}]+/u).filter(isPresent);
|
|
120
|
+
if (parts.length < 2)
|
|
121
|
+
continue;
|
|
122
|
+
const root = asciiFold(surface.recordID);
|
|
123
|
+
const floor = Math.min(HEAD_NOUN_PREFIX_FLOOR, root.length);
|
|
124
|
+
for (const part of parts) {
|
|
125
|
+
const folded = asciiFold(part);
|
|
126
|
+
if (folded.length >= floor && commonPrefixLength(folded, root) >= floor) {
|
|
127
|
+
emit(part, surface);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Non-Latin script: substrings shared by two or more surfaces of the same record + language.
|
|
132
|
+
const groups = new Map();
|
|
133
|
+
for (const surface of surfaces) {
|
|
134
|
+
if (!SHARED_SUBSTRING_SCRIPT.test(surface.phrase))
|
|
135
|
+
continue;
|
|
136
|
+
// Group `zh`, `zh-cn`, `zh-hant` together: they are writing systems for one vocabulary, and the
|
|
137
|
+
// simplified/traditional pair is exactly the evidence a shared substring needs.
|
|
138
|
+
const key = `${surface.recordID} ${surface.lang.split(/[-_]/u)[0]}`;
|
|
139
|
+
const pool = groups.get(key) ?? new Set();
|
|
140
|
+
pool.add(surface.phrase);
|
|
141
|
+
groups.set(key, pool);
|
|
142
|
+
}
|
|
143
|
+
const candidatesByGroup = new Map();
|
|
144
|
+
for (const [key, pool] of groups) {
|
|
145
|
+
if (pool.size < 2)
|
|
146
|
+
continue;
|
|
147
|
+
candidatesByGroup.set(key, sharedSubstringCandidates(pool));
|
|
148
|
+
}
|
|
149
|
+
for (const surface of surfaces) {
|
|
150
|
+
if (!SHARED_SUBSTRING_SCRIPT.test(surface.phrase))
|
|
151
|
+
continue;
|
|
152
|
+
const key = `${surface.recordID} ${surface.lang.split(/[-_]/u)[0]}`;
|
|
153
|
+
for (const candidate of candidatesByGroup.get(key) ?? []) {
|
|
154
|
+
if (surface.phrase.includes(candidate)) {
|
|
155
|
+
emit(candidate, surface);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return [...derived.values()];
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Length of the shared leading run of two strings.
|
|
163
|
+
*/
|
|
164
|
+
function commonPrefixLength(a, b) {
|
|
165
|
+
const limit = Math.min(a.length, b.length);
|
|
166
|
+
let i = 0;
|
|
167
|
+
while (i < limit && a[i] === b[i]) {
|
|
168
|
+
i++;
|
|
169
|
+
}
|
|
170
|
+
return i;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Substrings occurring in at least two DISTINCT members of `pool`, ranked by that count and then by length, capped at
|
|
174
|
+
* {@link NON_LATIN_HEAD_CANDIDATE_CAP}.
|
|
175
|
+
*
|
|
176
|
+
* A candidate never spans whitespace, and in a pool whose members contain whitespace a candidate must be a whole token
|
|
177
|
+
* of some member. That is what keeps Korean `공항 터미널` from contributing a fragment straddling the space.
|
|
178
|
+
*
|
|
179
|
+
* MAXIMAL candidates only: one contained in a longer candidate carried by the SAME number of surfaces is dropped, since
|
|
180
|
+
* counting can never separate the two. Every one of `ターミナル`'s five ja labels also contains `ターミ`, `ターミナ` and `ミナル`, so
|
|
181
|
+
* without this the group contributes four indistinguishable candidates and the Japan harvest returns four identical
|
|
182
|
+
* counts. `航站` survives next to `航站楼` because six surfaces carry it against that one's two.
|
|
183
|
+
*/
|
|
184
|
+
function sharedSubstringCandidates(pool) {
|
|
185
|
+
const phrases = [...pool];
|
|
186
|
+
const spaced = phrases.some((phrase) => /\s/u.test(phrase));
|
|
187
|
+
const tokens = spaced ? new Set(phrases.flatMap((phrase) => phrase.split(/\s+/u).filter(isPresent))) : null;
|
|
188
|
+
const counts = new Map();
|
|
189
|
+
for (const phrase of phrases) {
|
|
190
|
+
const local = new Set();
|
|
191
|
+
for (let length = NON_LATIN_HEAD_MIN_LENGTH; length <= phrase.length; length++) {
|
|
192
|
+
for (let start = 0; start + length <= phrase.length; start++) {
|
|
193
|
+
const candidate = phrase.slice(start, start + length);
|
|
194
|
+
if (/\s/u.test(candidate))
|
|
195
|
+
continue;
|
|
196
|
+
local.add(candidate);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
for (const candidate of local) {
|
|
200
|
+
counts.set(candidate, (counts.get(candidate) ?? 0) + 1);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const kept = [...counts].filter(([candidate, count]) => count >= 2 && (!tokens || tokens.has(candidate)));
|
|
204
|
+
return kept
|
|
205
|
+
.filter(([candidate, count]) => kept.every(([other, otherCount]) => other === candidate || otherCount !== count || !other.includes(candidate)))
|
|
206
|
+
.toSorted((a, b) => b[1] - a[1] || b[0].length - a[0].length || a[0].localeCompare(b[0]))
|
|
207
|
+
.slice(0, NON_LATIN_HEAD_CANDIDATE_CAP)
|
|
208
|
+
.map(([candidate]) => candidate);
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=head-nouns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"head-nouns.js","sourceRoot":"","sources":["../../../../src/tools/sub-venue/head-nouns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* @file Surface-form primitives for the sub-venue lexicon: the normalizer every phrase passes
|
|
7
|
+
* through, the phrase → record index built over the surfaces accumulated so far, and the operator
|
|
8
|
+
* that decides whether a feature's name contains a known designator.
|
|
9
|
+
*
|
|
10
|
+
* The two matching rules here are script-conditional, and both narrowings are load-bearing — see
|
|
11
|
+
* {@link NON_SPACING_SCRIPT} and {@link nameContainsSurfaces}.
|
|
12
|
+
*/
|
|
13
|
+
import type { SubVenueSurface } from "./table.ts";
|
|
14
|
+
/**
|
|
15
|
+
* Normalize a surface for the table: trim, collapse internal whitespace, and lowercase ONLY when the string is entirely
|
|
16
|
+
* in a bicameral script. `ターミナルビル` and `航站楼` pass through untouched; `Flughafenterminal` folds.
|
|
17
|
+
*/
|
|
18
|
+
export declare function normalizeSurface(text: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* A phrase → record index, keyed on the normalized phrase. Built by {@link buildSurfaceIndex} from the surfaces present
|
|
21
|
+
* before the harvest runs, and the reason a matched phrase can be attributed to the record it actually names.
|
|
22
|
+
*/
|
|
23
|
+
export type SurfaceIndex = ReadonlyMap<string, {
|
|
24
|
+
recordID: string;
|
|
25
|
+
recordKind: "designator" | "modifier";
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Index the surfaces accumulated so far by phrase. First writer wins, so a seed record beats a Wikidata alias that
|
|
29
|
+
* happens to collide — `terminal` stays the `terminal` designator even though it is also an Italian alias for it.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildSurfaceIndex(surfaces: readonly SubVenueSurface[]): SurfaceIndex;
|
|
32
|
+
/**
|
|
33
|
+
* Every known phrase found in `name`, as whole-token runs for spacing scripts and as substrings for non-spacing ones.
|
|
34
|
+
*
|
|
35
|
+
* Token-boundary matching for Latin script, not substring: `Nordterminal` is a real German compound in which `terminal`
|
|
36
|
+
* is a suffix, and a substring test would also fire on `Terminalstraße`. The compound case is a genuine miss and it is
|
|
37
|
+
* the right miss — admitting suffix matches would fire on every `-hall`/`-gate` compound in Germanic and Nordic street
|
|
38
|
+
* naming, which is exactly the confound class `Briggate`/`Kirkgate` represents.
|
|
39
|
+
*
|
|
40
|
+
* For Han/Kana names that rule finds nothing at all, because the script has no word boundaries: `第1ターミナル` splits into
|
|
41
|
+
* one token that matches no surface. There the LONGEST known substring is the correct operator, and the compound
|
|
42
|
+
* objection does not transfer — Japanese has no `-gate` street-name suffix class.
|
|
43
|
+
*/
|
|
44
|
+
export declare function nameContainsSurfaces(name: string, index: SurfaceIndex): string[];
|
|
45
|
+
//# sourceMappingURL=surfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaces.d.ts","sourceRoot":"","sources":["../../../../src/tools/sub-venue/surfaces.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAiBjD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,YAAY,GAAG,UAAU,CAAA;CAAE,CAAC,CAAA;AAE3G;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,YAAY,CASpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,EAAE,CAqBhF"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* @file Surface-form primitives for the sub-venue lexicon: the normalizer every phrase passes
|
|
7
|
+
* through, the phrase → record index built over the surfaces accumulated so far, and the operator
|
|
8
|
+
* that decides whether a feature's name contains a known designator.
|
|
9
|
+
*
|
|
10
|
+
* The two matching rules here are script-conditional, and both narrowings are load-bearing — see
|
|
11
|
+
* {@link NON_SPACING_SCRIPT} and {@link nameContainsSurfaces}.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Scripts whose case is meaningful to fold. Everything else is left as written — see {@link SubVenueSurface.phrase}.
|
|
15
|
+
*/
|
|
16
|
+
const CASE_FOLDING_SCRIPT = /^[\p{Script=Latin}\p{Script=Cyrillic}\p{Script=Greek}\d\s\p{P}]+$/u;
|
|
17
|
+
/**
|
|
18
|
+
* Scripts written without spaces between words, where a token split cannot find a designator and a SUBSTRING test is
|
|
19
|
+
* the correct operator. Han, Hiragana, Katakana; Hangul is excluded because Korean does space its words.
|
|
20
|
+
*
|
|
21
|
+
* The Germanic-compound argument that keeps {@link nameContainsSurfaces} token-bounded for Latin script does not
|
|
22
|
+
* transfer here — there is no `-gate`/`-hall` street-name suffix class in Japanese, and `第1ターミナル` is unreachable by any
|
|
23
|
+
* token split. Measured on the Japan extract: see the harvest counts in `corpus/data/PROVENANCE.md`.
|
|
24
|
+
*/
|
|
25
|
+
const NON_SPACING_SCRIPT = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}]/u;
|
|
26
|
+
/**
|
|
27
|
+
* Normalize a surface for the table: trim, collapse internal whitespace, and lowercase ONLY when the string is entirely
|
|
28
|
+
* in a bicameral script. `ターミナルビル` and `航站楼` pass through untouched; `Flughafenterminal` folds.
|
|
29
|
+
*/
|
|
30
|
+
export function normalizeSurface(text) {
|
|
31
|
+
const trimmed = text.trim().replaceAll(/\s+/gu, " ");
|
|
32
|
+
return CASE_FOLDING_SCRIPT.test(trimmed) ? trimmed.toLowerCase() : trimmed;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Index the surfaces accumulated so far by phrase. First writer wins, so a seed record beats a Wikidata alias that
|
|
36
|
+
* happens to collide — `terminal` stays the `terminal` designator even though it is also an Italian alias for it.
|
|
37
|
+
*/
|
|
38
|
+
export function buildSurfaceIndex(surfaces) {
|
|
39
|
+
const index = new Map();
|
|
40
|
+
for (const surface of surfaces) {
|
|
41
|
+
if (index.has(surface.phrase))
|
|
42
|
+
continue;
|
|
43
|
+
index.set(surface.phrase, { recordID: surface.recordID, recordKind: surface.recordKind });
|
|
44
|
+
}
|
|
45
|
+
return index;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Every known phrase found in `name`, as whole-token runs for spacing scripts and as substrings for non-spacing ones.
|
|
49
|
+
*
|
|
50
|
+
* Token-boundary matching for Latin script, not substring: `Nordterminal` is a real German compound in which `terminal`
|
|
51
|
+
* is a suffix, and a substring test would also fire on `Terminalstraße`. The compound case is a genuine miss and it is
|
|
52
|
+
* the right miss — admitting suffix matches would fire on every `-hall`/`-gate` compound in Germanic and Nordic street
|
|
53
|
+
* naming, which is exactly the confound class `Briggate`/`Kirkgate` represents.
|
|
54
|
+
*
|
|
55
|
+
* For Han/Kana names that rule finds nothing at all, because the script has no word boundaries: `第1ターミナル` splits into
|
|
56
|
+
* one token that matches no surface. There the LONGEST known substring is the correct operator, and the compound
|
|
57
|
+
* objection does not transfer — Japanese has no `-gate` street-name suffix class.
|
|
58
|
+
*/
|
|
59
|
+
export function nameContainsSurfaces(name, index) {
|
|
60
|
+
const normalized = normalizeSurface(name);
|
|
61
|
+
const hits = new Set();
|
|
62
|
+
for (const token of normalized.split(/[\s,()/]+/u)) {
|
|
63
|
+
const stripped = token.replaceAll(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu, "");
|
|
64
|
+
if (stripped && index.has(stripped)) {
|
|
65
|
+
hits.add(stripped);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (NON_SPACING_SCRIPT.test(normalized)) {
|
|
69
|
+
for (const [phrase] of index) {
|
|
70
|
+
if (NON_SPACING_SCRIPT.test(phrase) && normalized.includes(phrase)) {
|
|
71
|
+
hits.add(phrase);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return [...hits];
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=surfaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaces.js","sourceRoot":"","sources":["../../../../src/tools/sub-venue/surfaces.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;GAEG;AACH,MAAM,mBAAmB,GAAG,oEAAoE,CAAA;AAEhG;;;;;;;GAOG;AACH,MAAM,kBAAkB,GAAG,yDAAyD,CAAA;AAEpF;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IAEpD,OAAO,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;AAC3E,CAAC;AAQD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAoC;IACrE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuE,CAAA;IAE5F,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,SAAQ;QACvC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IAC1F,CAAC;IAED,OAAO,KAAK,CAAA;AACb,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,KAAmB;IACrE,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAA;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAE9B,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,mCAAmC,EAAE,EAAE,CAAC,CAAA;QAE1E,IAAI,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACnB,CAAC;IACF,CAAC;IAED,IAAI,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACzC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YAC9B,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACpE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACjB,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;AACjB,CAAC"}
|