diff --git a/.agents/skills/jobdanmark-search/cli/src/commands/detail.ts b/.agents/skills/jobdanmark-search/cli/src/commands/detail.ts index 9bc49e13..88183365 100644 --- a/.agents/skills/jobdanmark-search/cli/src/commands/detail.ts +++ b/.agents/skills/jobdanmark-search/cli/src/commands/detail.ts @@ -56,6 +56,21 @@ function cleanText(text: string): string { return text.replace(/\s+/g, " ").trim() } +/** + * JSON-LD descriptions arrive as HTML (schema.org allows it, jobdanmark uses + * it). Render them to the same newline-separated plain text the rendered-HTML + * branch produces, so `detail` emits one description shape whichever page + * layout it hit: tags gone, entities decoded, one line per block element. + */ +function descriptionToText(html: string | undefined): string { + if (!html) return "" + return parse(html) + .structuredText.split("\n") + .map(cleanText) + .filter(Boolean) + .join("\n") +} + function normalizeUrl(value: string | null | undefined): string | null { if (!value) return null const decoded = value.replace(/&/g, "&") @@ -115,7 +130,7 @@ function fromJsonLd(jobPosting: JsonLdJobPosting, slug: string, url: string): De postalCode: address?.postalCode ?? null, addressCountry: address?.addressCountry ?? null, }, - description: jobPosting.description ?? "", + description: descriptionToText(jobPosting.description), applyUrl: null, } } diff --git a/.agents/skills/jobdanmark-search/cli/tests/detail-jsonld.test.ts b/.agents/skills/jobdanmark-search/cli/tests/detail-jsonld.test.ts index 208d82e9..42070c40 100644 --- a/.agents/skills/jobdanmark-search/cli/tests/detail-jsonld.test.ts +++ b/.agents/skills/jobdanmark-search/cli/tests/detail-jsonld.test.ts @@ -50,11 +50,43 @@ describe("parseJobPostingFromHtml JSON-LD", () => { postalCode: "5000", addressCountry: "DK", }, - description: "

Build reliable pipelines.

", + description: "Build reliable pipelines.", applyUrl: null, }); }); + test("renders an HTML description to the rendered-branch text shape", () => { + // add-portal.md Step 4: a detail description is "readable text (entities + // decoded, tags stripped, paragraph breaks preserved)". The rendered-HTML + // fallback already emits one line per

/

  • ; the JSON-LD branch passed + // the markup through verbatim, so the same command produced two shapes. + const posting = { + "@type": "JobPosting", + title: "Udvikler", + description: + "

    Vi søger en udvikler til R&D.

    Second para
    line two

    ", + }; + + const parsed = parseJobPostingFromHtml( + pageWithScripts(JSON.stringify(posting)), + "udvikler", + "https://jobdanmark.dk/job/udvikler", + ); + + expect(parsed.description).toBe("Vi søger en udvikler til R&D.\nSecond para\nline two\nPython & Go\nSQL"); + expect(parsed.description).not.toMatch(/<[^>]+>/); + }); + + test("leaves a plain-text description unchanged and an absent one empty", () => { + const withText = { "@type": "JobPosting", title: "A", description: "Plain prose, no markup." }; + const without = { "@type": "JobPosting", title: "B" }; + + expect(parseJobPostingFromHtml(pageWithScripts(JSON.stringify(withText)), "a", "https://jobdanmark.dk/job/a").description).toBe( + "Plain prose, no markup.", + ); + expect(parseJobPostingFromHtml(pageWithScripts(JSON.stringify(without)), "b", "https://jobdanmark.dk/job/b").description).toBe(""); + }); + test("skips malformed scripts and finds a JobPosting in an array", () => { const scripts = [ "{not-json", diff --git a/CHANGELOG.md b/CHANGELOG.md index c47515f8..4a3deffd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,21 @@ per-file diff commands. ### Fixed +- **`jobdanmark-search detail` renders a JSON-LD description as text instead of passing + the markup through** (`.agents/skills/jobdanmark-search/cli/src/commands/detail.ts`, + `tests/detail-jsonld.test.ts`) - the JSON-LD branch emitted `jobPosting.description` + verbatim, so `detail --format plain` printed + `description:

    Vi søger en udvikler til R&D.