From d3eea27b90aeaaeeb2cbf9d702bca3ff4d9f9f87 Mon Sep 17 00:00:00 2001 From: Oscar Madera <80536682+oscarbol09@users.noreply.github.com> Date: Tue, 21 Jul 2026 01:11:17 -0500 Subject: [PATCH] fix(portals): depth-track div extraction so nested job descriptions aren't truncated (#204) The jobindex and linkedin detail parsers matched description containers with a non-greedy regex that stops at the first inner , so any posting whose description contains nested divs was silently truncated (jobindex dropped later sections; linkedin dropped everything after the first block). Replaces the regex with a depth-tracked extractDivContent scanner that walks div open/close markers to the matching close. Verified: truncation bug reproduced against real markup fixtures, depth arithmetic correct (no off-by-one/infinite-loop), 28 tests pass network-free, no regression on non-nested divs. Malformed-HTML over-grabs rather than truncates - the safer failure, cleaned by downstream stripTags/decode. By @oscarbol09. --- .../cli/src/commands/detail.ts | 8 +-- .../skills/jobindex-search/cli/src/helpers.ts | 27 +++++++++ .../jobindex-search/cli/tests/parsing.test.ts | 54 ++++++++++++++++- .../skills/linkedin-search/cli/src/helpers.ts | 41 +++++++++++-- .../linkedin-search/cli/tests/parsing.test.ts | 60 ++++++++++++++++++- 5 files changed, 179 insertions(+), 11 deletions(-) diff --git a/.agents/skills/jobindex-search/cli/src/commands/detail.ts b/.agents/skills/jobindex-search/cli/src/commands/detail.ts index afb3cbd..0e82094 100644 --- a/.agents/skills/jobindex-search/cli/src/commands/detail.ts +++ b/.agents/skills/jobindex-search/cli/src/commands/detail.ts @@ -1,6 +1,6 @@ import { defineCommand, option } from "@bunli/core" import { z } from "zod" -import { htmlFetch, writeError } from "../helpers.js" +import { htmlFetch, writeError, extractDivContent } from "../helpers.js" const BASE_URL = "https://www.jobindex.dk" @@ -180,9 +180,9 @@ function parseDetailPage(html: string, url: string, id: string): DetailResult { let description: string | null = null // Try job-text class first - const jobTextMatch = html.match(/class="job-text"[^>]*>([\s\S]*?)<\/div>\s*(?:
We are...
+We are...
\n ', + ); + }); + + test("returns null when class not found", () => { + expect(extractDivContent("We are hiring!
+