diff --git a/.agents/skills/jobdanmark-search/cli/src/commands/search.ts b/.agents/skills/jobdanmark-search/cli/src/commands/search.ts index f0faee8..e311c09 100644 --- a/.agents/skills/jobdanmark-search/cli/src/commands/search.ts +++ b/.agents/skills/jobdanmark-search/cli/src/commands/search.ts @@ -39,6 +39,18 @@ function toContractDate(value: string | null): string | null { return match ? `${match[3]}-${match[2]}-${match[1]}` : (value ?? null) } +// Live companyAddress values put the city after the postcode either as +// "Lautruphoej 2, 2750 Ballerup" or "2670, Greve". The comma fallback +// requires a non-digit after the comma so a 4-digit street number +// ("Vejlevej 1234, 7100 Vejle") never wins over the real postcode. +function extractCity(address: string | null): string | null { + if (!address) return null + const city = + address.match(/\d{4}\s+(.+)$/)?.[1] ?? address.match(/\d{4}\s*,\s*([^\d,].*)$/)?.[1] + const trimmed = city?.trim() + return trimmed ? trimmed : null +} + export function normalizeItem(item: ApiSearchItem): Record { const relativeUrl = item.url const fullUrl = relativeUrl.startsWith("http") @@ -83,7 +95,7 @@ export function normalizeItem(item: ApiSearchItem): Record { coverImage, silhouetteLogo: item.silhouetteLogo, company: item.companyName, - location: item.companyAddress?.match(/\d{4}\s+(.+)$/)?.[1] ?? null, + location: extractCity(item.companyAddress), date: toContractDate(item.publishedDate), deadline: toContractDate(item.applicationDeadline), } diff --git a/.agents/skills/jobdanmark-search/cli/tests/search-normalization.test.ts b/.agents/skills/jobdanmark-search/cli/tests/search-normalization.test.ts index 6a63111..1c20287 100644 --- a/.agents/skills/jobdanmark-search/cli/tests/search-normalization.test.ts +++ b/.agents/skills/jobdanmark-search/cli/tests/search-normalization.test.ts @@ -44,6 +44,33 @@ describe("Jobdanmark search normalization", () => { expect(result.company).toBe("Statens It"); }); + test("extracts the city when a comma follows the postcode (live jobdanmark shape)", () => { + const result = normalizeItem({ + ...item(), + companyAddress: "2670, Greve", + }); + + expect(result.location).toBe("Greve"); + }); + + test("trims trailing whitespace from the extracted city", () => { + const result = normalizeItem({ + ...item(), + companyAddress: "7100, Vejle ", + }); + + expect(result.location).toBe("Vejle"); + }); + + test("does not mistake a 4-digit street number for the postcode", () => { + const result = normalizeItem({ + ...item(), + companyAddress: "Vejlevej 1234, 7100 Vejle", + }); + + expect(result.location).toBe("Vejle"); + }); + test("survives a null companyAddress from the API", () => { const result = normalizeItem({ ...item(), diff --git a/CHANGELOG.md b/CHANGELOG.md index 20901ba..1887902 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,13 @@ per-file diff commands. ### Fixed +- **`jobdanmark-search` extracts the city when a comma follows the postcode** - the + `location` regex required whitespace after the 4-digit postcode, but live + `companyAddress` values frequently read `"2670, Greve"`; those results emitted + `location: null` (7 of 30 in a live sample), so `/scrape`'s geography/commute filter + (Rule 3) had nothing to act on. The extraction now accepts an optional comma, trims the + captured city, and still refuses to mistake a 4-digit street number for the postcode. + Pinned by three new cases in `tests/search-normalization.test.ts`. - **Example-CV bullets no longer swallowed as LaTeX optional labels** - every placeholder bullet written as `\item [text]` (11 in `cv/main_example.tex`, 3 in `06-cover-letter-templates.md`'s taught template) let LaTeX parse the bracketed text as