schema.org source: a microdata or RDFa JobPosting inside a page-level item (a WebPage body, mainEntity) is never read #589
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#589
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 at
95348908d, reading the microdata and RDFa readers and running the schema.org source on wrapped postings.Checked again on 2026-10-01 against
mainat0a5cad587: still present.The microdata and RDFa readers return only the outermost items on a page, and the schema.org source looks for a
JobPostingonly among those. Many site themes putitemscope itemtype="https://schema.org/WebPage"on<body>, so on such a site the posting is not outermost and is never seen: it is not read as a property of the WebPage either, because it carries noitemprop. A posting attached asitemprop="mainEntity"is read, but only as a nested value that_postingsnever looks inside. #176 added microdata and RDFa and taught JSON-LD to followmainEntity; the markup spellings did not get the same.Related to #176, which added these readers and claimed
mainEntityis followed; that holds for JSON-LD only.plugins/builtin/htmlutil.py:499-505(_outermostdrops every item that has an item above it),:508-524(extract_microdata) and:527-544(extract_rdfa);:476-493(_read_itemdoes not descend into a child that opens its own item, and keeps it only when it is a property);plugins/builtin/__init__.py:256-264(_postingschecks only the top-level objects'@type) and:362(SchemaOrgSource.parse); comparehtmlutil.py:396-413(_flatten, which followsmainEntity,@graph,itemListElementanditem, but only for JSON-LD). The extension does the same:postulo-chromiumsrc/lib/parse.js:192-203(outermost,microdata) and:212(rdfa).<body itemscope itemtype="https://schema.org/WebPage">around the sameJobPosting<div>that is read correctly under a plain<body>:extract_microdatareturns[{'@type': 'WebPage'}]andSchemaOrgSource().parsereturnsNone.itemprop="mainEntity"inside that body:extract_microdatareturns[{'@type': 'WebPage', 'mainEntity': {'@type': 'JobPosting', ...}}], andparsestill returnsNone.<body vocab="https://schema.org/" typeof="WebPage">around<div typeof="JobPosting">:extract_rdfareturns[{'@type': 'WebPage'}], andparsereturnsNone.In each case the capture falls through to
page-metadata, which loses the company, location, salary, dates and employment type the page stated in its markup.itempropmarkup) are often built on themes that wrap the whole page in aWebPageitem, so the structured data is there and is not used.itemscopeand noitempropas a top-level item whatever its ancestors are, and do the same for RDFatypeofwithoutproperty. Then pass the microdata and RDFa objects through_flatten(extended to look inside nested property values such asmainEntity,hasPartandabout), so a posting held inside another item is found exactly as it is in JSON-LD. Make the same change inpostulo-chromium'sparse.jsso the two readers stay identical.Done when
tests/fixtures/postings/, a WebPage-wrapped microdata posting and amainEntityone (plus an RDFa variant), read bytests/test_source_corpus.pywith their expected title and company; today they read asNone.postulo-chromium'stest/corpus.test.mjs.