diff --git a/pcweb/meta/meta.py b/pcweb/meta/meta.py index 5727374ea..ed7602e29 100644 --- a/pcweb/meta/meta.py +++ b/pcweb/meta/meta.py @@ -287,6 +287,16 @@ def blog_index_jsonld(posts: list[tuple[str, dict]], url: str) -> rx.Component: return rx.el.script(json.dumps(data), type="application/ld+json") +def jsonld_script(data: dict) -> rx.Component: + """Create a JSON-LD script tag from a dict. + + Adds ``@context: https://schema.org`` when not already present. + """ + if "@context" not in data: + data = {"@context": "https://schema.org", **data} + return rx.el.script(json.dumps(data), type="application/ld+json") + + def faq_jsonld(faq_schema: dict) -> rx.Component: """Create a FAQPage JSON-LD script tag from a pre-built schema dict.""" return rx.el.script(json.dumps(faq_schema), type="application/ld+json") diff --git a/pcweb/pages/docs/__init__.py b/pcweb/pages/docs/__init__.py index c011c69e1..58c86557d 100644 --- a/pcweb/pages/docs/__init__.py +++ b/pcweb/pages/docs/__init__.py @@ -13,6 +13,7 @@ from pcweb.constants import REFLEX_ASSETS_CDN from pcweb.docgen_pipeline import get_docgen_toc, render_docgen_document from pcweb.flexdown import xd +from pcweb.meta.meta import jsonld_script from pcweb.pages.docs.component import multi_docs from pcweb.pages.library_previews import components_previews_pages from pcweb.route import Route @@ -256,9 +257,14 @@ def get_component(doc: str, title: str): return None d = load_flexdown_doc(actual_doc_path) + ldjson = d.metadata.get("ldjson") def comp(): - return (get_toc(d, actual_doc_path), xd.render(d, actual_doc_path)) + toc = get_toc(d, actual_doc_path) + rendered = xd.render(d, actual_doc_path) + if isinstance(ldjson, dict) and ldjson: + rendered = rx.fragment(jsonld_script(ldjson), rendered) + return (toc, rendered) return make_docpage(resolved.route, resolved.display_title, doc, comp) @@ -273,9 +279,18 @@ def get_component_docgen(virtual_doc: str, actual_path: str, title: str): if virtual_doc.startswith("docs/library"): return handle_library_doc(virtual_doc, actual_path, title, resolved) - def comp(_actual=actual_path): + # Load metadata to check for ldjson (docgen docs use flexdown for metadata). + try: + _meta_doc = load_flexdown_doc(actual_path) + ldjson = _meta_doc.metadata.get("ldjson") + except (OSError, ValueError): + ldjson = None + + def comp(_actual=actual_path, _ldjson=ldjson): toc = get_docgen_toc(_actual) rendered = render_docgen_document(_actual) + if isinstance(_ldjson, dict) and _ldjson: + rendered = rx.fragment(jsonld_script(_ldjson), rendered) return (toc, rendered) return make_docpage(resolved.route, resolved.display_title, virtual_doc, comp)