Reading a page: a JobPosting's identifier is matched by its name, so every posting on a careers site counts as this page's #15
Labels
No labels
bug
documentation
enhancement
performance
security
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo-chromium#15
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo-chromium at
7998de372, reading how the popup picks the posting a page is about, and checked against the core's copy of the same code at postulo 95348908d.Related to postulo/postulo#177.
matchesUrlfalls back to comparing a posting'sidentifierwith the page's address, but reads the identifier throughtext(), which prefersnameovervalue. In schema.org an identifier is usually aPropertyValuewhosenameis the issuing organisation and whosevalueis the id (Google's own JobPosting example is{"@type": "PropertyValue", "name": "<company>", "value": "1234567"}). So the test is really "does the company's name appear in the address". On a careers site whose host or path holds a one-word company name, every posting on the page matches: the popup fills its form with the first posting rather than the one being looked at, and a results page is never offered as a list to tick.src/lib/parse.js:403-412,text():return String(one.name || one.value || "").trim();src/lib/parse.js:556-570,matchesUrl():const identifier = text(posting.identifier); return identifier.length >= 4 && here.includes(identifier.toLowerCase());, a substring test against host, path and query together.src/lib/parse.js:581-587,bestPosting():found.find((posting) => matchesUrl(posting, url)) || found[0], so an earlier posting that matches by identifier wins over a later one whoseurlnames the page exactly.src/lib/parse.js:799-830,readPostings(): setshere: matchesUrl(posting, url)on every listed posting.src/popup.js:90-96: offers the tick list only whenlisted.length > 1 && !listed.some((posting) => posting.here).plugins/builtin/__init__.py:110-117(_text),:237-253(_matches_url) and:267-275(_best_posting).https://careers.blackmesa.example/jobs/202carries JSON-LD for postings 101 ("Welder"), 202 ("Physicist") and 303, each with its ownurland withidentifier: {"@type": "PropertyValue", "name": "BlackMesa", "value": "<n>"}.text(posting.identifier)is"BlackMesa"for all three, which the address contains, so posting 101 matches first and the form opens with "Welder".careers.blackmesa.example/jobs?q=all, every posting is markedhere, so the popup treats it as a single posting's page and the tick list (#177) never appears.Running the core's
registry.parse_pageon the snapshot with the page above gives "Welder"; with the identifier's name changed to "Black Mesa Research" it gives "Physicist", the right answer.value(or the identifier itself when it is a plain string or number), never itsname, in a helper of its own rather thantext(). Compare it with whole path or query segments of the address, not as a substring of host, path and query. InbestPosting, tryurl,@idandsameAsacross all postings before trying any identifier. Make the same change in the core's_matches_urland_best_posting(the extension mirrors the server's reading, as #3 asks), with the shared corpus fixture below on both sides.Related, same functions:
sameUrl()(parse.js:541-549, core_same_url) keeps the whole query string, so the posting page opened from a link carrying?utm_source=...never matches its ownurland falls back to the first posting too. Ignoring well-known tracking parameters (utm_*,gclid,fbclid,ref) when comparing would close that as well.Done when
PropertyValueidentifier named after the company, on an address that contains that name, reads as the posting whoseurlis the page intest/parse.test.mjs, and the same fixture in the core's parser tests reads the same.readPostingson that site's results page marks no postinghere, intest/parse.test.mjs.