# retoor import json import re from molodetz import config from molodetz.assets import static_url from molodetz.seo_meta_text import DEFAULT_DESCRIPTION DEFAULT_OG_IMAGE_PATH = "/static/media/flyer-elite-twice.jpg" def base_url(request): if config.SITE_URL: return config.SITE_URL return str(request.base_url).rstrip("/") def _clean(text): return re.sub(r"[*_`#\[\]]", "", text or "").strip() def website_schema(request): base = base_url(request) return { "@context": "https://schema.org", "@type": "WebSite", "name": config.APP_TITLE, "url": base + "/", "inLanguage": "en", "potentialAction": { "@type": "SearchAction", "target": base + "/docs/search?q={search_term_string}", "query-input": "required name=search_term_string", }, } def organization_schema(request): base = base_url(request) return {"@context": "https://schema.org", "@type": "Organization", "name": config.APP_TITLE, "url": base + "/"} def breadcrumb_schema(request, breadcrumbs): base = base_url(request) return { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [ {"@type": "ListItem", "position": index + 1, "name": _clean(name), "item": base + path} for index, (name, path) in enumerate(breadcrumbs) ], } def article_schema(request, post, author): base = base_url(request) return { "@context": "https://schema.org", "@type": "BlogPosting", "headline": _clean(post["title"]), "datePublished": post.get("published_at") or post.get("created_at"), "dateModified": post.get("updated_at"), "inLanguage": "en", "mainEntityOfPage": f"{base}/posts/{post['slug']}", "author": {"@type": "Person", "name": author["username"] if author else "retoor", "url": f"{base}/people/{author['username'] if author else 'retoor'}"}, "publisher": {"@type": "Organization", "name": config.APP_TITLE}, } def profile_schema(request, person): base = base_url(request) return { "@context": "https://schema.org", "@type": "ProfilePage", "mainEntity": {"@type": "Person", "name": person["username"], "url": f"{base}/people/{person['username']}"}, } def base_seo_context( request, title, description=None, robots="index,follow", og_type="website", og_image=None, breadcrumbs=None, schemas=None, prev_url=None, next_url=None, keywords=None, ): base = base_url(request) canonical = base + request.url.path page = request.query_params.get("page") if page: canonical += f"?page={page}" image = og_image or static_url(DEFAULT_OG_IMAGE_PATH) if image.startswith("/"): image = base + image crumbs = [(_clean(name), path) for name, path in (breadcrumbs or [])] all_schemas = list(schemas or []) if crumbs: all_schemas.append(breadcrumb_schema(request, crumbs)) full_title = f"{title} | {config.APP_TITLE}" if title and title != config.APP_TITLE else config.APP_TITLE return { "title": full_title, "description": description or DEFAULT_DESCRIPTION, "robots": robots, "canonical": canonical, "og_type": og_type, "og_image": image, "breadcrumbs": crumbs, "json_ld": [json.dumps(schema, ensure_ascii=False).replace("