@mailwoman/corpus 8.5.0 → 9.0.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 +1 -1
- package/out/src/adapter.d.ts +41 -0
- package/out/src/adapter.d.ts.map +1 -1
- package/out/src/adapter.js +46 -1
- package/out/src/adapter.js.map +1 -1
- package/out/src/adapters/ban/adapter.d.ts +4 -3
- package/out/src/adapters/ban/adapter.d.ts.map +1 -1
- package/out/src/adapters/ban/adapter.js +60 -67
- package/out/src/adapters/ban/adapter.js.map +1 -1
- package/out/src/adapters/ban/street-decompose.d.ts.map +1 -1
- package/out/src/adapters/ban/street-decompose.js +18 -25
- package/out/src/adapters/ban/street-decompose.js.map +1 -1
- package/out/src/adapters/fcc-bdc/adapter.d.ts +0 -6
- package/out/src/adapters/fcc-bdc/adapter.d.ts.map +1 -1
- package/out/src/adapters/fcc-bdc/adapter.js +2 -24
- package/out/src/adapters/fcc-bdc/adapter.js.map +1 -1
- package/out/src/adapters/geonames/adapter.d.ts.map +1 -1
- package/out/src/adapters/geonames/adapter.js +70 -76
- package/out/src/adapters/geonames/adapter.js.map +1 -1
- package/out/src/adapters/geonames-postal/adapter.d.ts.map +1 -1
- package/out/src/adapters/geonames-postal/adapter.js +44 -49
- package/out/src/adapters/geonames-postal/adapter.js.map +1 -1
- package/out/src/adapters/gnaf/adapter.d.ts.map +1 -1
- package/out/src/adapters/gnaf/adapter.js +4 -7
- package/out/src/adapters/gnaf/adapter.js.map +1 -1
- package/out/src/adapters/gnaf/assemble.d.ts.map +1 -1
- package/out/src/adapters/gnaf/assemble.js +6 -11
- package/out/src/adapters/gnaf/assemble.js.map +1 -1
- package/out/src/adapters/openaddresses/adapter.d.ts.map +1 -1
- package/out/src/adapters/openaddresses/adapter.js +2 -7
- package/out/src/adapters/openaddresses/adapter.js.map +1 -1
- package/out/src/adapters/overture/adapter.d.ts.map +1 -1
- package/out/src/adapters/overture/adapter.js +3 -7
- package/out/src/adapters/overture/adapter.js.map +1 -1
- package/out/src/adapters/state-hi-schools/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-hi-schools/adapter.js +55 -73
- package/out/src/adapters/state-hi-schools/adapter.js.map +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.js +58 -76
- package/out/src/adapters/state-ia-contractors/adapter.js.map +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.js +67 -85
- package/out/src/adapters/state-ny-notaries/adapter.js.map +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.js +69 -87
- package/out/src/adapters/state-tx-notaries/adapter.js.map +1 -1
- package/out/src/adapters/synth-po-box/adapter.d.ts.map +1 -1
- package/out/src/adapters/synth-po-box/adapter.js +7 -15
- package/out/src/adapters/synth-po-box/adapter.js.map +1 -1
- package/out/src/adapters/tiger/street-decompose.d.ts.map +1 -1
- package/out/src/adapters/tiger/street-decompose.js +18 -27
- package/out/src/adapters/tiger/street-decompose.js.map +1 -1
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts +3 -3
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.js +62 -80
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.js.map +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.js +60 -82
- package/out/src/adapters/usgov-imls-pls/adapter.js.map +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.js +58 -65
- package/out/src/adapters/usgov-irs-bmf/adapter.js.map +1 -1
- package/out/src/adapters/usgov-nad/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-nad/adapter.js +5 -8
- package/out/src/adapters/usgov-nad/adapter.js.map +1 -1
- package/out/src/adapters/usgov-nppes/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-nppes/adapter.js +58 -76
- package/out/src/adapters/usgov-nppes/adapter.js.map +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 +51 -71
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js.map +1 -1
- package/out/src/adapters/wof-admin-jp/adapter.d.ts.map +1 -1
- package/out/src/adapters/wof-admin-jp/adapter.js +24 -6
- package/out/src/adapters/wof-admin-jp/adapter.js.map +1 -1
- package/out/src/build.d.ts.map +1 -1
- package/out/src/build.js +2 -1
- package/out/src/build.js.map +1 -1
- package/out/src/golden.d.ts +5 -0
- package/out/src/golden.d.ts.map +1 -1
- package/out/src/golden.js +23 -9
- package/out/src/golden.js.map +1 -1
- package/out/src/parquet-wrapper/reader.d.ts +8 -0
- package/out/src/parquet-wrapper/reader.d.ts.map +1 -1
- package/out/src/parquet-wrapper/reader.js +16 -0
- package/out/src/parquet-wrapper/reader.js.map +1 -1
- package/out/src/parquet-wrapper/schema.d.ts +4 -0
- package/out/src/parquet-wrapper/schema.d.ts.map +1 -1
- package/out/src/parquet-wrapper/schema.js.map +1 -1
- package/out/src/parquet.d.ts.map +1 -1
- package/out/src/parquet.js +2 -13
- package/out/src/parquet.js.map +1 -1
- package/out/src/shard-recipes/anchor-absorption.d.ts.map +1 -1
- package/out/src/shard-recipes/anchor-absorption.js +2 -1
- package/out/src/shard-recipes/anchor-absorption.js.map +1 -1
- package/out/src/shard-recipes/country-balanced.d.ts.map +1 -1
- package/out/src/shard-recipes/country-balanced.js +68 -60
- package/out/src/shard-recipes/country-balanced.js.map +1 -1
- package/out/src/shard-recipes/fr-fragment.d.ts.map +1 -1
- package/out/src/shard-recipes/fr-fragment.js +8 -5
- package/out/src/shard-recipes/fr-fragment.js.map +1 -1
- package/out/src/shard-recipes/fr-order.d.ts.map +1 -1
- package/out/src/shard-recipes/fr-order.js +14 -58
- 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 +11 -58
- package/out/src/shard-recipes/german.js.map +1 -1
- package/out/src/shard-recipes/index.d.ts.map +1 -1
- package/out/src/shard-recipes/index.js +2 -0
- package/out/src/shard-recipes/index.js.map +1 -1
- package/out/src/shard-recipes/intersection.d.ts +2 -2
- package/out/src/shard-recipes/intersection.d.ts.map +1 -1
- package/out/src/shard-recipes/intersection.js +24 -62
- package/out/src/shard-recipes/intersection.js.map +1 -1
- package/out/src/shard-recipes/locale.d.ts.map +1 -1
- package/out/src/shard-recipes/locale.js +14 -16
- package/out/src/shard-recipes/locale.js.map +1 -1
- package/out/src/shard-recipes/no-fragment.d.ts.map +1 -1
- package/out/src/shard-recipes/no-fragment.js +8 -5
- package/out/src/shard-recipes/no-fragment.js.map +1 -1
- package/out/src/shard-recipes/no-street-led.d.ts.map +1 -1
- package/out/src/shard-recipes/no-street-led.js +8 -5
- package/out/src/shard-recipes/no-street-led.js.map +1 -1
- package/out/src/shard-recipes/po-box-cedex.d.ts +3 -3
- package/out/src/shard-recipes/po-box-cedex.d.ts.map +1 -1
- package/out/src/shard-recipes/po-box-cedex.js +51 -94
- package/out/src/shard-recipes/po-box-cedex.js.map +1 -1
- package/out/src/shard-recipes/scaffold.d.ts +59 -9
- package/out/src/shard-recipes/scaffold.d.ts.map +1 -1
- package/out/src/shard-recipes/scaffold.js +51 -30
- package/out/src/shard-recipes/scaffold.js.map +1 -1
- package/out/src/shard-recipes/street-affix.d.ts.map +1 -1
- package/out/src/shard-recipes/street-affix.js +56 -82
- package/out/src/shard-recipes/street-affix.js.map +1 -1
- package/out/src/shard-recipes/sub-venue-sources.d.ts +231 -0
- package/out/src/shard-recipes/sub-venue-sources.d.ts.map +1 -0
- package/out/src/shard-recipes/sub-venue-sources.js +669 -0
- package/out/src/shard-recipes/sub-venue-sources.js.map +1 -0
- package/out/src/shard-recipes/sub-venue.d.ts +269 -0
- package/out/src/shard-recipes/sub-venue.d.ts.map +1 -0
- package/out/src/shard-recipes/sub-venue.js +709 -0
- package/out/src/shard-recipes/sub-venue.js.map +1 -0
- package/out/src/shard-recipes/unit.d.ts +1 -1
- package/out/src/shard-recipes/unit.d.ts.map +1 -1
- package/out/src/shard-recipes/unit.js +22 -64
- package/out/src/shard-recipes/unit.js.map +1 -1
- package/out/src/split.d.ts +7 -0
- package/out/src/split.d.ts.map +1 -1
- package/out/src/split.js +7 -0
- package/out/src/split.js.map +1 -1
- package/out/src/synthesize.d.ts.map +1 -1
- package/out/src/synthesize.js +1 -12
- package/out/src/synthesize.js.map +1 -1
- package/out/src/tools/align-shard.d.ts.map +1 -1
- package/out/src/tools/align-shard.js +3 -7
- package/out/src/tools/align-shard.js.map +1 -1
- package/out/src/tools/audit.d.ts.map +1 -1
- package/out/src/tools/audit.js +4 -4
- package/out/src/tools/audit.js.map +1 -1
- package/out/src/tools/corpus-stats.d.ts +2 -2
- package/out/src/tools/corpus-stats.d.ts.map +1 -1
- package/out/src/tools/corpus-stats.js +18 -31
- package/out/src/tools/corpus-stats.js.map +1 -1
- package/out/src/tools/fetch/download.d.ts.map +1 -1
- package/out/src/tools/fetch/download.js +5 -6
- package/out/src/tools/fetch/download.js.map +1 -1
- package/out/src/tools/fetch/imls-pls.d.ts.map +1 -1
- package/out/src/tools/fetch/imls-pls.js +2 -2
- package/out/src/tools/fetch/imls-pls.js.map +1 -1
- package/out/src/tools/fetch/index.d.ts +14 -1
- package/out/src/tools/fetch/index.d.ts.map +1 -1
- package/out/src/tools/fetch/index.js +14 -1
- package/out/src/tools/fetch/index.js.map +1 -1
- package/out/src/tools/fetch/nad.d.ts +1 -1
- package/out/src/tools/fetch/nad.js +1 -1
- package/out/src/tools/fetch/nppes.d.ts.map +1 -1
- package/out/src/tools/fetch/nppes.js +2 -1
- package/out/src/tools/fetch/nppes.js.map +1 -1
- package/out/src/tools/fetch/openaddresses.d.ts +1 -1
- package/out/src/tools/fetch/openaddresses.js +1 -1
- package/out/src/tools/fetch/ourairports.d.ts +45 -0
- package/out/src/tools/fetch/ourairports.d.ts.map +1 -0
- package/out/src/tools/fetch/ourairports.js +123 -0
- package/out/src/tools/fetch/ourairports.js.map +1 -0
- package/out/src/tools/fetch/wikidata-subvenue.d.ts +171 -0
- package/out/src/tools/fetch/wikidata-subvenue.d.ts.map +1 -0
- package/out/src/tools/fetch/wikidata-subvenue.js +275 -0
- package/out/src/tools/fetch/wikidata-subvenue.js.map +1 -0
- package/out/src/tools/golden-expand.d.ts.map +1 -1
- package/out/src/tools/golden-expand.js +18 -16
- package/out/src/tools/golden-expand.js.map +1 -1
- package/out/src/tools/golden-promote.d.ts.map +1 -1
- package/out/src/tools/golden-promote.js +12 -6
- package/out/src/tools/golden-promote.js.map +1 -1
- package/out/src/tools/golden-relabel-street.d.ts +196 -0
- package/out/src/tools/golden-relabel-street.d.ts.map +1 -0
- package/out/src/tools/golden-relabel-street.js +513 -0
- package/out/src/tools/golden-relabel-street.js.map +1 -0
- package/out/src/tools/index.d.ts +4 -0
- package/out/src/tools/index.d.ts.map +1 -1
- package/out/src/tools/index.js +4 -0
- package/out/src/tools/index.js.map +1 -1
- package/out/src/tools/jsonl-to-parquet.d.ts.map +1 -1
- package/out/src/tools/jsonl-to-parquet.js +3 -2
- package/out/src/tools/jsonl-to-parquet.js.map +1 -1
- package/out/src/tools/lint-shard-vocab.d.ts.map +1 -1
- package/out/src/tools/lint-shard-vocab.js +3 -2
- package/out/src/tools/lint-shard-vocab.js.map +1 -1
- package/out/src/tools/lint-shard.d.ts +3 -3
- package/out/src/tools/lint-shard.d.ts.map +1 -1
- package/out/src/tools/lint-shard.js +23 -32
- package/out/src/tools/lint-shard.js.map +1 -1
- package/out/src/tools/overlay-manifest.d.ts.map +1 -1
- package/out/src/tools/overlay-manifest.js +2 -1
- package/out/src/tools/overlay-manifest.js.map +1 -1
- package/out/src/tools/overture-subvenue.d.ts +112 -0
- package/out/src/tools/overture-subvenue.d.ts.map +1 -0
- package/out/src/tools/overture-subvenue.js +144 -0
- package/out/src/tools/overture-subvenue.js.map +1 -0
- package/out/src/tools/shard-kryptonite.d.ts +1 -1
- package/out/src/tools/shard-kryptonite.d.ts.map +1 -1
- package/out/src/tools/shard-kryptonite.js +5 -4
- package/out/src/tools/shard-kryptonite.js.map +1 -1
- package/out/src/tools/shard-translit.d.ts +6 -3
- package/out/src/tools/shard-translit.d.ts.map +1 -1
- package/out/src/tools/shard-translit.js +8 -6
- package/out/src/tools/shard-translit.js.map +1 -1
- package/out/src/tools/sub-venue-lexicon.d.ts +507 -0
- package/out/src/tools/sub-venue-lexicon.d.ts.map +1 -0
- package/out/src/tools/sub-venue-lexicon.js +817 -0
- package/out/src/tools/sub-venue-lexicon.js.map +1 -0
- package/out/src/tools/sub-venue-promotions.d.ts +94 -0
- package/out/src/tools/sub-venue-promotions.d.ts.map +1 -0
- package/out/src/tools/sub-venue-promotions.js +266 -0
- package/out/src/tools/sub-venue-promotions.js.map +1 -0
- package/out/src/wof-json.d.ts +2 -2
- package/out/src/wof-json.d.ts.map +1 -1
- package/out/src/wof-json.js +5 -8
- package/out/src/wof-json.js.map +1 -1
- package/package.json +8 -8
- package/src/adapter.ts +58 -1
- package/src/adapters/ban/adapter.ts +55 -65
- package/src/adapters/ban/street-decompose.ts +17 -25
- package/src/adapters/fcc-bdc/adapter.ts +2 -33
- package/src/adapters/geonames/adapter.ts +64 -72
- package/src/adapters/geonames-postal/adapter.ts +42 -50
- package/src/adapters/gnaf/adapter.ts +4 -7
- package/src/adapters/gnaf/assemble.ts +6 -10
- package/src/adapters/openaddresses/adapter.ts +2 -7
- package/src/adapters/overture/adapter.ts +3 -6
- package/src/adapters/state-hi-schools/adapter.ts +50 -73
- package/src/adapters/state-ia-contractors/adapter.ts +52 -76
- package/src/adapters/state-ny-notaries/adapter.ts +61 -85
- package/src/adapters/state-tx-notaries/adapter.ts +60 -84
- package/src/adapters/synth-po-box/adapter.ts +7 -17
- package/src/adapters/tiger/street-decompose.ts +21 -31
- package/src/adapters/usgov-hrsa-fqhc/adapter.ts +61 -84
- package/src/adapters/usgov-imls-pls/adapter.ts +54 -82
- package/src/adapters/usgov-irs-bmf/adapter.ts +53 -63
- package/src/adapters/usgov-nad/adapter.ts +5 -8
- package/src/adapters/usgov-nppes/adapter.ts +51 -75
- package/src/adapters/usgov-samhsa-treatment-locator/adapter.ts +45 -71
- package/src/adapters/wof-admin-jp/adapter.ts +34 -8
- package/src/build.ts +2 -1
- package/src/golden.ts +24 -9
- package/src/parquet-wrapper/reader.ts +19 -0
- package/src/parquet-wrapper/schema.ts +4 -0
- package/src/parquet.ts +3 -16
- package/src/shard-recipes/anchor-absorption.ts +2 -1
- package/src/shard-recipes/country-balanced.ts +69 -70
- package/src/shard-recipes/fr-fragment.ts +10 -7
- package/src/shard-recipes/fr-order.ts +13 -63
- package/src/shard-recipes/german.ts +12 -65
- package/src/shard-recipes/index.ts +2 -0
- package/src/shard-recipes/intersection.ts +32 -60
- package/src/shard-recipes/locale.ts +14 -16
- package/src/shard-recipes/no-fragment.ts +10 -7
- package/src/shard-recipes/no-street-led.ts +10 -7
- package/src/shard-recipes/po-box-cedex.ts +68 -119
- package/src/shard-recipes/scaffold.ts +82 -28
- package/src/shard-recipes/street-affix.ts +58 -95
- package/src/shard-recipes/sub-venue-sources.ts +895 -0
- package/src/shard-recipes/sub-venue.ts +982 -0
- package/src/shard-recipes/unit.ts +22 -70
- package/src/split.ts +7 -0
- package/src/synthesize.ts +1 -15
- package/src/tools/align-shard.ts +3 -6
- package/src/tools/audit.ts +6 -5
- package/src/tools/corpus-stats.ts +25 -33
- package/src/tools/fetch/download.ts +7 -5
- package/src/tools/fetch/imls-pls.ts +2 -2
- package/src/tools/fetch/index.ts +14 -1
- package/src/tools/fetch/nad.ts +1 -1
- package/src/tools/fetch/nppes.ts +2 -1
- package/src/tools/fetch/openaddresses.ts +1 -1
- package/src/tools/fetch/ourairports.ts +166 -0
- package/src/tools/fetch/wikidata-subvenue.ts +386 -0
- package/src/tools/golden-expand.ts +18 -13
- package/src/tools/golden-promote.ts +15 -6
- package/src/tools/golden-relabel-street.ts +748 -0
- package/src/tools/index.ts +4 -0
- package/src/tools/jsonl-to-parquet.ts +3 -2
- package/src/tools/lint-shard-vocab.ts +3 -2
- package/src/tools/lint-shard.ts +33 -36
- package/src/tools/overlay-manifest.ts +2 -1
- package/src/tools/overture-subvenue.ts +215 -0
- package/src/tools/shard-kryptonite.ts +5 -4
- package/src/tools/shard-translit.ts +12 -7
- package/src/tools/sub-venue-lexicon.ts +1250 -0
- package/src/tools/sub-venue-promotions.ts +330 -0
- package/src/wof-json.ts +5 -8
|
@@ -33,11 +33,12 @@
|
|
|
33
33
|
import { spawnSync } from "node:child_process"
|
|
34
34
|
|
|
35
35
|
import type { ComponentTag } from "@mailwoman/core/types"
|
|
36
|
+
import { dataRootPath } from "@mailwoman/core/utils"
|
|
36
37
|
|
|
37
38
|
import { stableSourceID } from "../adapter.ts"
|
|
38
39
|
import { alignRow } from "../align.ts"
|
|
39
40
|
import type { CanonicalRow } from "../types.ts"
|
|
40
|
-
import { makeMulberry32, type ShardRecipe } from "./scaffold.ts"
|
|
41
|
+
import { makeMulberry32, readCSVRecords, type ShardRecipe } from "./scaffold.ts"
|
|
41
42
|
|
|
42
43
|
/* oxlint-disable sister-software/no-unnamed-threshold -- the bare decimals below are weighted-sampler
|
|
43
44
|
cutoffs, not thresholds: `const r = random()` followed by a cascade of `r < 0.4` branches IS the
|
|
@@ -45,7 +46,7 @@ import { makeMulberry32, type ShardRecipe } from "./scaffold.ts"
|
|
|
45
46
|
would hide the distribution behind a wall of identifiers. Genuine thresholds in these files are
|
|
46
47
|
extracted as named constants above. */
|
|
47
48
|
|
|
48
|
-
const SOURCE = { zip: "
|
|
49
|
+
const SOURCE = { zip: dataRootPath("oa-cache", "fr__countrywide.zip"), csv: "fr/countrywide.csv" }
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
52
|
* Ordinal suffixes used in French house numbers (BAN corpus), to cover the "8 bis" sub-mode.
|
|
@@ -71,47 +72,9 @@ interface FrTuple {
|
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
/**
|
|
74
|
-
*
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const out: string[] = []
|
|
78
|
-
let cur = ""
|
|
79
|
-
let inQ = false
|
|
80
|
-
|
|
81
|
-
for (let i = 0; i < line.length; i++) {
|
|
82
|
-
const c = line[i]
|
|
83
|
-
|
|
84
|
-
if (inQ) {
|
|
85
|
-
if (c === '"') {
|
|
86
|
-
if (line[i + 1] === '"') {
|
|
87
|
-
cur += '"'
|
|
88
|
-
|
|
89
|
-
i++
|
|
90
|
-
} else {
|
|
91
|
-
inQ = false
|
|
92
|
-
}
|
|
93
|
-
} else {
|
|
94
|
-
cur += c
|
|
95
|
-
}
|
|
96
|
-
} else if (c === '"') {
|
|
97
|
-
inQ = true
|
|
98
|
-
} else if (c === ",") {
|
|
99
|
-
out.push(cur)
|
|
100
|
-
cur = ""
|
|
101
|
-
} else {
|
|
102
|
-
cur += c
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
out.push(cur)
|
|
107
|
-
|
|
108
|
-
return out
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Stream FR tuples out of the cached OA zip. The countrywide extract is GB-scale; cap with `head` to stay under V8's
|
|
113
|
-
* string limit. Only keeps rows with a house_number (the shard's core signal) and a postcode (required for
|
|
114
|
-
* reversed-order rendering to be meaningful).
|
|
75
|
+
* Stream FR tuples out of the cached OA zip. The countrywide extract is GB-scale; cap with `head` so the whole file
|
|
76
|
+
* never has to be held in memory. Only keeps rows with a house_number (the shard's core signal) and a postcode
|
|
77
|
+
* (required for reversed-order rendering to be meaningful).
|
|
115
78
|
*/
|
|
116
79
|
function readTuples(limit: number): FrTuple[] {
|
|
117
80
|
const maxLines = Math.max(limit * 8, 40_000) + 1
|
|
@@ -127,28 +90,15 @@ function readTuples(limit: number): FrTuple[] {
|
|
|
127
90
|
return []
|
|
128
91
|
}
|
|
129
92
|
|
|
130
|
-
const lines = r.stdout.toString("utf8").split(/\r?\n/)
|
|
131
|
-
|
|
132
|
-
if (lines.length < 2) return []
|
|
133
|
-
const header = splitCSV(lines[0]!).map((h) => h.trim().toLowerCase())
|
|
134
|
-
const idx = (name: string): number => header.indexOf(name)
|
|
135
|
-
|
|
136
|
-
const iNum = idx("number"),
|
|
137
|
-
iStreet = idx("street"),
|
|
138
|
-
iCity = idx("city"),
|
|
139
|
-
iPost = idx("postcode")
|
|
140
|
-
|
|
141
|
-
const get = (cells: string[], i: number): string => (i >= 0 && i < cells.length ? (cells[i] ?? "").trim() : "")
|
|
142
93
|
const tuples: FrTuple[] = []
|
|
143
94
|
const seen = new Set<string>()
|
|
144
95
|
|
|
145
|
-
for (
|
|
146
|
-
if (
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
const
|
|
150
|
-
const
|
|
151
|
-
const postcode = get(cells, iPost)
|
|
96
|
+
for (const row of readCSVRecords(r.stdout)) {
|
|
97
|
+
if (tuples.length >= limit) break
|
|
98
|
+
const street = row.street ?? ""
|
|
99
|
+
const locality = row.city ?? ""
|
|
100
|
+
const house_number = row.number ?? ""
|
|
101
|
+
const postcode = row.postcode ?? ""
|
|
152
102
|
|
|
153
103
|
// Require all four fields: HN is the signal; postcode drives reversed-order variants.
|
|
154
104
|
if (!street || !locality || !house_number || !postcode) continue
|
|
@@ -216,7 +166,7 @@ export const frOrderRecipe: ShardRecipe = {
|
|
|
216
166
|
console.error(` ${SOURCE.csv}: ${pool.length} unique tuples (capped read)`)
|
|
217
167
|
|
|
218
168
|
if (!pool.length) {
|
|
219
|
-
throw new Error(
|
|
169
|
+
throw new Error(`No FR tuples found — is ${SOURCE.zip} present?`)
|
|
220
170
|
}
|
|
221
171
|
|
|
222
172
|
let emitted = 0
|
|
@@ -17,10 +17,12 @@
|
|
|
17
17
|
|
|
18
18
|
import { spawnSync } from "node:child_process"
|
|
19
19
|
|
|
20
|
+
import { dataRootPath } from "@mailwoman/core/utils"
|
|
21
|
+
|
|
20
22
|
import { stableSourceID } from "../adapter.ts"
|
|
21
23
|
import { alignRow } from "../align.ts"
|
|
22
24
|
import { synthesizeGermanRow, type LocaleBaseTuple } from "../synthesize-german.ts"
|
|
23
|
-
import { makeMulberry32, type ShardRecipe } from "./scaffold.ts"
|
|
25
|
+
import { makeMulberry32, readCSVRecords, type ShardRecipe } from "./scaffold.ts"
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
28
|
* A German OA source (cached zip) + the Bundesland the file covers (OA's REGION column is empty for DE).
|
|
@@ -37,48 +39,10 @@ interface GermanSource {
|
|
|
37
39
|
* Berlin (a city-state, region==locality); sn/statewide → Sachsen.
|
|
38
40
|
*/
|
|
39
41
|
const SOURCES: GermanSource[] = [
|
|
40
|
-
{ zip: "
|
|
41
|
-
{ zip: "
|
|
42
|
+
{ zip: dataRootPath("oa-cache", "de__berlin.zip"), csv: "de/berlin.csv", region: "Berlin" },
|
|
43
|
+
{ zip: dataRootPath("oa-cache", "de__sn__statewide.zip"), csv: "de/sn/statewide.csv", region: "Sachsen" },
|
|
42
44
|
]
|
|
43
45
|
|
|
44
|
-
/**
|
|
45
|
-
* Minimal RFC-4180-ish splitter (handles quoted fields).
|
|
46
|
-
*/
|
|
47
|
-
function splitCSV(line: string): string[] {
|
|
48
|
-
const out: string[] = []
|
|
49
|
-
let cur = ""
|
|
50
|
-
let inQ = false
|
|
51
|
-
|
|
52
|
-
for (let i = 0; i < line.length; i++) {
|
|
53
|
-
const c = line[i]!
|
|
54
|
-
|
|
55
|
-
if (inQ) {
|
|
56
|
-
if (c === '"') {
|
|
57
|
-
if (line[i + 1] === '"') {
|
|
58
|
-
cur += '"'
|
|
59
|
-
|
|
60
|
-
i++
|
|
61
|
-
} else {
|
|
62
|
-
inQ = false
|
|
63
|
-
}
|
|
64
|
-
} else {
|
|
65
|
-
cur += c
|
|
66
|
-
}
|
|
67
|
-
} else if (c === '"') {
|
|
68
|
-
inQ = true
|
|
69
|
-
} else if (c === ",") {
|
|
70
|
-
out.push(cur)
|
|
71
|
-
cur = ""
|
|
72
|
-
} else {
|
|
73
|
-
cur += c
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
out.push(cur)
|
|
78
|
-
|
|
79
|
-
return out
|
|
80
|
-
}
|
|
81
|
-
|
|
82
46
|
/**
|
|
83
47
|
* Stream real German tuples out of a cached OA zip (buffered `unzip -p`).
|
|
84
48
|
*/
|
|
@@ -91,35 +55,18 @@ function readGermanTuples(source: GermanSource): LocaleBaseTuple[] {
|
|
|
91
55
|
return []
|
|
92
56
|
}
|
|
93
57
|
|
|
94
|
-
const lines = r.stdout.toString("utf8").split(/\r?\n/)
|
|
95
|
-
|
|
96
|
-
if (lines.length < 2) return []
|
|
97
|
-
const header = splitCSV(lines[0]!).map((h) => h.trim().toLowerCase())
|
|
98
|
-
const idx = (name: string): number => header.indexOf(name)
|
|
99
|
-
|
|
100
|
-
const iNum = idx("number"),
|
|
101
|
-
iStreet = idx("street"),
|
|
102
|
-
iCity = idx("city"),
|
|
103
|
-
iRegion = idx("region"),
|
|
104
|
-
iPost = idx("postcode")
|
|
105
|
-
|
|
106
|
-
const get = (cells: string[], i: number): string => (i >= 0 && i < cells.length ? (cells[i] ?? "").trim() : "")
|
|
107
58
|
const tuples: LocaleBaseTuple[] = []
|
|
108
59
|
const seen = new Set<string>()
|
|
109
60
|
|
|
110
|
-
for (
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
if (!lineStr) continue
|
|
114
|
-
const cells = splitCSV(lineStr)
|
|
115
|
-
const street = get(cells, iStreet)
|
|
116
|
-
const locality = get(cells, iCity)
|
|
61
|
+
for (const row of readCSVRecords(r.stdout)) {
|
|
62
|
+
const street = row.street ?? ""
|
|
63
|
+
const locality = row.city ?? ""
|
|
117
64
|
|
|
118
65
|
if (!street || !locality) continue
|
|
119
|
-
const house_number =
|
|
120
|
-
const postcode =
|
|
66
|
+
const house_number = row.number ?? ""
|
|
67
|
+
const postcode = row.postcode ?? ""
|
|
121
68
|
// OA's REGION column is empty for DE — fall back to the source's Bundesland (set per file).
|
|
122
|
-
const region =
|
|
69
|
+
const region = row.region || source.region || ""
|
|
123
70
|
const key = `${house_number}|${street}|${locality}|${postcode}`.toLowerCase()
|
|
124
71
|
|
|
125
72
|
if (seen.has(key)) continue
|
|
@@ -165,7 +112,7 @@ export const germanRecipe: ShardRecipe = {
|
|
|
165
112
|
}
|
|
166
113
|
|
|
167
114
|
if (!pool.length) {
|
|
168
|
-
throw new Error(
|
|
115
|
+
throw new Error(`No German tuples found — are the cached zips present in ${dataRootPath("oa-cache")}?`)
|
|
169
116
|
}
|
|
170
117
|
|
|
171
118
|
let emitted = 0
|
|
@@ -32,6 +32,7 @@ import { siBareVillageRecipe } from "./si-bare-village.ts"
|
|
|
32
32
|
import { streetAffixRecipe } from "./street-affix.ts"
|
|
33
33
|
import { streetBareRecipe } from "./street-bare.ts"
|
|
34
34
|
import { streetRecipe } from "./street.ts"
|
|
35
|
+
import { subVenueRecipe } from "./sub-venue.ts"
|
|
35
36
|
import { unitRecipe } from "./unit.ts"
|
|
36
37
|
|
|
37
38
|
export * from "./scaffold.ts"
|
|
@@ -64,6 +65,7 @@ const RECIPES: readonly ShardRecipe[] = [
|
|
|
64
65
|
countryBalancedRecipe,
|
|
65
66
|
boundaryStressRecipe,
|
|
66
67
|
anchorAbsorptionRecipe,
|
|
68
|
+
subVenueRecipe,
|
|
67
69
|
]
|
|
68
70
|
|
|
69
71
|
/**
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
* External inputs (`--edges-dir`, opts.edgesDir; both already on disk — do not re-download):
|
|
31
31
|
*
|
|
32
32
|
* - <edges-dir>/tl_2023_{17031,34027,50023}_edges.shp (unzipped TIGER 2023 EDGES; default
|
|
33
|
-
* /
|
|
34
|
-
* - /
|
|
33
|
+
* `$MAILWOMAN_DATA_ROOT/census/tiger2023-edges`, where `mailwoman situs interpolation` puts them)
|
|
34
|
+
* - `$MAILWOMAN_DATA_ROOT/oa-cache/us__il__cook.zip` (ZIP→city tails)
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
37
|
import { spawnSync } from "node:child_process"
|
|
@@ -39,12 +39,13 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"
|
|
|
39
39
|
|
|
40
40
|
import type { DuckDBConnection } from "@duckdb/node-api"
|
|
41
41
|
import type { ComponentTag } from "@mailwoman/core/types"
|
|
42
|
-
import { repoRootPath } from "@mailwoman/core/utils"
|
|
42
|
+
import { dataRootPath, repoRootPath } from "@mailwoman/core/utils"
|
|
43
|
+
import { JSONSpliterator } from "spliterator"
|
|
43
44
|
|
|
44
45
|
import { stableSourceID } from "../adapter.ts"
|
|
45
46
|
import { alignRow } from "../align.ts"
|
|
46
47
|
import type { CanonicalRow, LabeledRow } from "../types.ts"
|
|
47
|
-
import { makeMulberry32, type ShardRecipe } from "./scaffold.ts"
|
|
48
|
+
import { makeMulberry32, readCSVRecords, type ShardRecipe } from "./scaffold.ts"
|
|
48
49
|
|
|
49
50
|
interface County {
|
|
50
51
|
fips: string
|
|
@@ -60,7 +61,13 @@ const TRAIN_COUNTIES: readonly County[] = [
|
|
|
60
61
|
const GOLDEN_COUNTIES: readonly County[] = [{ fips: "50023", state: "VT", regime: "rural" }]
|
|
61
62
|
|
|
62
63
|
const EVAL_GOLD_PATH = repoRootPath("data", "eval", "external", "intersection-real.jsonl")
|
|
63
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Where `mailwoman situs interpolation` unpacks the per-county TIGER EDGES shapefiles — a Census download, so it sits
|
|
66
|
+
* beside the other Census vintages under `census/`. `--edges-dir` overrides it.
|
|
67
|
+
*/
|
|
68
|
+
const DEFAULT_EDGES_DIR = dataRootPath("census", "tiger2023-edges")
|
|
69
|
+
|
|
70
|
+
const OA_COOK = { zip: dataRootPath("oa-cache", "us__il__cook.zip"), csv: "us/il/cook.csv" }
|
|
64
71
|
|
|
65
72
|
/**
|
|
66
73
|
* One real crossing extracted from a county's TIGER EDGES shapefile.
|
|
@@ -157,52 +164,22 @@ function weightedPick<T extends { w: number }>(items: readonly T[], random: () =
|
|
|
157
164
|
}
|
|
158
165
|
|
|
159
166
|
/**
|
|
160
|
-
*
|
|
167
|
+
* Order-insensitive crossing key, for eval-leakage exclusion + pair dedup.
|
|
161
168
|
*/
|
|
162
|
-
|
|
163
|
-
const out: string[] = []
|
|
164
|
-
let cur = ""
|
|
165
|
-
let inQ = false
|
|
166
|
-
|
|
167
|
-
for (let i = 0; i < line.length; i++) {
|
|
168
|
-
const c = line[i]
|
|
169
|
-
|
|
170
|
-
if (inQ) {
|
|
171
|
-
if (c === '"') {
|
|
172
|
-
if (line[i + 1] === '"') {
|
|
173
|
-
cur += '"'
|
|
174
|
-
|
|
175
|
-
i++
|
|
176
|
-
} else {
|
|
177
|
-
inQ = false
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
cur += c
|
|
181
|
-
}
|
|
182
|
-
} else if (c === '"') {
|
|
183
|
-
inQ = true
|
|
184
|
-
} else if (c === ",") {
|
|
185
|
-
out.push(cur)
|
|
186
|
-
cur = ""
|
|
187
|
-
} else {
|
|
188
|
-
cur += c
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
out.push(cur)
|
|
193
|
-
|
|
194
|
-
return out
|
|
195
|
-
}
|
|
169
|
+
const pairKey = (a: string, b: string): string => [a.toLowerCase(), b.toLowerCase()].toSorted().join("\u001F")
|
|
196
170
|
|
|
197
171
|
/**
|
|
198
|
-
*
|
|
172
|
+
* One row of the intersection eval gold — the shape this recipe reads to exclude eval crossings.
|
|
199
173
|
*/
|
|
200
|
-
|
|
174
|
+
interface EvalGoldRow {
|
|
175
|
+
node: number | string
|
|
176
|
+
components: { intersection_a: string; intersection_b: string }
|
|
177
|
+
}
|
|
201
178
|
|
|
202
179
|
/**
|
|
203
180
|
* Load the eval's crossings so neither train nor golden ever sees them.
|
|
204
181
|
*/
|
|
205
|
-
function readEvalExclusions(): { nodes: Set<number>; pairs: Set<string> } {
|
|
182
|
+
async function readEvalExclusions(): Promise<{ nodes: Set<number>; pairs: Set<string> }> {
|
|
206
183
|
const nodes = new Set<number>()
|
|
207
184
|
const pairs = new Set<string>()
|
|
208
185
|
|
|
@@ -212,9 +189,7 @@ function readEvalExclusions(): { nodes: Set<number>; pairs: Set<string> } {
|
|
|
212
189
|
return { nodes, pairs }
|
|
213
190
|
}
|
|
214
191
|
|
|
215
|
-
for (const
|
|
216
|
-
if (!line) continue
|
|
217
|
-
const row = JSON.parse(line)
|
|
192
|
+
for await (const row of JSONSpliterator.fromAsync<EvalGoldRow>(EVAL_GOLD_PATH)) {
|
|
218
193
|
nodes.add(Number(row.node))
|
|
219
194
|
pairs.add(pairKey(row.components.intersection_a, row.components.intersection_b))
|
|
220
195
|
}
|
|
@@ -285,20 +260,12 @@ function buildZipCityMap(): Map<string, string> {
|
|
|
285
260
|
return new Map()
|
|
286
261
|
}
|
|
287
262
|
|
|
288
|
-
const lines = r.stdout.toString("utf8").split(/\r?\n/)
|
|
289
|
-
|
|
290
|
-
if (lines.length < 2) return new Map()
|
|
291
|
-
const header = splitCSV(lines[0]!).map((h) => h.trim().toLowerCase())
|
|
292
|
-
const iCity = header.indexOf("city")
|
|
293
|
-
const iPost = header.indexOf("postcode")
|
|
294
263
|
const counts = new Map<string, Map<string, number>>()
|
|
295
264
|
|
|
296
265
|
// zip → Map(city → n)
|
|
297
|
-
for (
|
|
298
|
-
|
|
299
|
-
const
|
|
300
|
-
const city = (cells[iCity] ?? "").trim()
|
|
301
|
-
const zip = (cells[iPost] ?? "").trim()
|
|
266
|
+
for (const row of readCSVRecords(r.stdout)) {
|
|
267
|
+
const city = row.city ?? ""
|
|
268
|
+
const zip = row.postcode ?? ""
|
|
302
269
|
|
|
303
270
|
if (!city || !/^\d{5}$/.test(zip) || BAD_NAME.test(city)) continue
|
|
304
271
|
let byCity = counts.get(zip)
|
|
@@ -486,15 +453,20 @@ export const intersectionRecipe: ShardRecipe = {
|
|
|
486
453
|
name: "intersection",
|
|
487
454
|
description: "Real-pair intersection rows (US): TIGER 2023 EDGES crossings → audited intersection_a/b labels",
|
|
488
455
|
mode: "generate",
|
|
489
|
-
options: [
|
|
456
|
+
options: [
|
|
457
|
+
{
|
|
458
|
+
flag: "--edges-dir <dir>",
|
|
459
|
+
description: `Unzipped TIGER 2023 EDGES dir. Default ${DEFAULT_EDGES_DIR}`,
|
|
460
|
+
},
|
|
461
|
+
],
|
|
490
462
|
async run(opts, write) {
|
|
491
463
|
// Legacy build-intersection-shard.mjs seeded `mulberry32(opts.seed)`.
|
|
492
464
|
const random = makeMulberry32(opts.seed)
|
|
493
465
|
const count = opts.count ?? 40_000
|
|
494
466
|
const source = opts.sourceName ?? "synth-intersection"
|
|
495
|
-
const edgesDir = opts.edgesDir ??
|
|
467
|
+
const edgesDir = opts.edgesDir ?? DEFAULT_EDGES_DIR
|
|
496
468
|
const counties = opts.golden ? GOLDEN_COUNTIES : TRAIN_COUNTIES
|
|
497
|
-
const exclusions = readEvalExclusions()
|
|
469
|
+
const exclusions = await readEvalExclusions()
|
|
498
470
|
|
|
499
471
|
console.error(` eval exclusions: ${exclusions.nodes.size} nodes, ${exclusions.pairs.size} pairs`)
|
|
500
472
|
|
|
@@ -86,26 +86,26 @@ export interface LocaleCountrySource {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
|
-
* Per-country OA sources + the source name used in the corpus. DE/FR
|
|
90
|
-
*
|
|
91
|
-
* IT the cached national zip under `$MAILWOMAN_DATA_ROOT` (#241; the fresh ES extract is
|
|
92
|
-
* raw-CNIG conform map is gone). DE carries a per-part `region` fallback (its REGION column is
|
|
93
|
-
* international-order tail needs it, #327). FR/NL/IT/ES REGION is populated per-row (ES = comunidad
|
|
94
|
-
* regione, NL = province).
|
|
89
|
+
* Per-country OA sources + the source name used in the corpus. DE/FR read their historical build inputs, the cached
|
|
90
|
+
* zips under `$MAILWOMAN_DATA_ROOT/oa-cache` — materialize them there to regenerate. ES/NL read the extracted
|
|
91
|
+
* countrywide CSVs and IT the cached national zip under `$MAILWOMAN_DATA_ROOT` (#241; the fresh ES extract is
|
|
92
|
+
* OA-conformed, so the old raw-CNIG conform map is gone). DE carries a per-part `region` fallback (its REGION column is
|
|
93
|
+
* empty; the international-order tail needs it, #327). FR/NL/IT/ES REGION is populated per-row (ES = comunidad
|
|
94
|
+
* autónoma, IT = regione, NL = province).
|
|
95
95
|
*/
|
|
96
96
|
const COUNTRY_SOURCES: Record<string, LocaleCountrySource> = {
|
|
97
97
|
DE: {
|
|
98
98
|
source: "synth-german",
|
|
99
99
|
corpusVersion: "0.4.0",
|
|
100
100
|
parts: [
|
|
101
|
-
{ zip: "
|
|
102
|
-
{ zip: "
|
|
101
|
+
{ zip: dataRootPath("oa-cache", "de__berlin.zip"), csv: "de/berlin.csv", region: "Berlin" },
|
|
102
|
+
{ zip: dataRootPath("oa-cache", "de__sn__statewide.zip"), csv: "de/sn/statewide.csv", region: "Sachsen" },
|
|
103
103
|
],
|
|
104
104
|
},
|
|
105
105
|
FR: {
|
|
106
106
|
source: "synth-fr",
|
|
107
107
|
corpusVersion: "0.4.0",
|
|
108
|
-
parts: [{ zip: "
|
|
108
|
+
parts: [{ zip: dataRootPath("oa-cache", "fr__countrywide.zip"), csv: "fr/countrywide.csv" }],
|
|
109
109
|
},
|
|
110
110
|
NL: {
|
|
111
111
|
source: "synth-nl",
|
|
@@ -144,7 +144,7 @@ const COUNTRY_SOURCES: Record<string, LocaleCountrySource> = {
|
|
|
144
144
|
parts: [{ path: dataRootPath("openaddresses", "extracted", "nz", "countrywide.csv"), districtAsLocality: true }],
|
|
145
145
|
},
|
|
146
146
|
GB: {
|
|
147
|
-
// HM Land Registry Price Paid Data tuples (25.67M rows
|
|
147
|
+
// HM Land Registry Price Paid Data tuples (25.67M rows out of the PPD ingest). PPD's DISTRICT is the
|
|
148
148
|
// postal town (locality) and CITY is the dependent locality — legitimately EMPTY on the majority of rows
|
|
149
149
|
// (most GB addresses have no dependent locality). `districtAsLocality` maps DISTRICT→locality and, when
|
|
150
150
|
// present, CITY→dependent_locality; the `readTuples` gate above only drops a row when BOTH are empty, so
|
|
@@ -256,9 +256,8 @@ export async function readTuples(part: LocalePart, rng: () => number): Promise<L
|
|
|
256
256
|
|
|
257
257
|
try {
|
|
258
258
|
// CSVSpliterator handles OA's quoted fields (embedded commas/newlines) and CRLF row terminators
|
|
259
|
-
// (spliterator ≥ 3.2.0); `header: false` yields the header row too, so
|
|
260
|
-
// from
|
|
261
|
-
// on 10M+ real OA rows — the only raw-cell difference was a trailing CR on the discarded HASH column.
|
|
259
|
+
// (spliterator ≥ 3.2.0); `header: false` yields the header row too, so the column index is built
|
|
260
|
+
// from that first row rather than from a header option.
|
|
262
261
|
for await (const cells of CSVSpliterator.fromAsync<string[]>(input, {
|
|
263
262
|
mode: "array",
|
|
264
263
|
header: false,
|
|
@@ -315,9 +314,8 @@ export async function readTuples(part: LocalePart, rng: () => number): Promise<L
|
|
|
315
314
|
// dependent_locality. When DISTRICT is empty (~18% of NZ rows), fall back to CITY → locality with no
|
|
316
315
|
// sub-locality. GB PPD tuples flip which side is legitimately empty — on the MAJORITY of GB rows CITY
|
|
317
316
|
// (the dependent_locality) is empty and DISTRICT (the locality) is populated, so the gate below only
|
|
318
|
-
// drops a `districtAsLocality` row when BOTH are empty,
|
|
319
|
-
//
|
|
320
|
-
// {@link LocalePart.districtAsLocality}.
|
|
317
|
+
// drops a `districtAsLocality` row when BOTH are empty, never when CITY alone is — gating on CITY
|
|
318
|
+
// alone silently discards most of the GB source. See {@link LocalePart.districtAsLocality}.
|
|
321
319
|
let locality: string | null
|
|
322
320
|
let dependent_locality: string | undefined
|
|
323
321
|
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* list. Diacritic-KEEPING normalizer, matching the board (see the norm docstring).
|
|
36
36
|
*/
|
|
37
37
|
|
|
38
|
-
import {
|
|
38
|
+
import { TextSpliterator } from "spliterator"
|
|
39
39
|
|
|
40
40
|
import { alignAndWrite, makeMulberry32, readTuples, type ShardRecipe, shardSourceID } from "./scaffold.ts"
|
|
41
41
|
|
|
@@ -100,12 +100,15 @@ export const noFragmentRecipe: ShardRecipe = {
|
|
|
100
100
|
)
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
const excluded = new Set(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
const excluded = new Set<string>()
|
|
104
|
+
|
|
105
|
+
for await (const line of TextSpliterator.fromAsync(excludePath)) {
|
|
106
|
+
const trimmed = line.trim()
|
|
107
|
+
|
|
108
|
+
if (trimmed && !trimmed.startsWith("#")) {
|
|
109
|
+
excluded.add(trimmed)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
109
112
|
|
|
110
113
|
if (!excluded.size) throw new Error(`no-fragment: --exclude-surfaces "${excludePath}" listed no surfaces`)
|
|
111
114
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* 3. pc-first "«pc» «city», «st» «n»" (the 7% floor — the anchor the others converge to)
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import { TextSpliterator } from "spliterator"
|
|
20
20
|
|
|
21
21
|
import { alignAndWrite, makeMulberry32, readTuples, type ShardRecipe, shardSourceID } from "./scaffold.ts"
|
|
22
22
|
|
|
@@ -62,12 +62,15 @@ export const noStreetLedRecipe: ShardRecipe = {
|
|
|
62
62
|
)
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
const excluded = new Set(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
const excluded = new Set<string>()
|
|
66
|
+
|
|
67
|
+
for await (const line of TextSpliterator.fromAsync(excludePath)) {
|
|
68
|
+
const trimmed = line.trim()
|
|
69
|
+
|
|
70
|
+
if (trimmed && !trimmed.startsWith("#")) {
|
|
71
|
+
excluded.add(trimmed)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
71
74
|
|
|
72
75
|
if (!excluded.size) throw new Error(`no-street-led: --exclude-surfaces "${excludePath}" listed no surfaces`)
|
|
73
76
|
|