-
Notifications
You must be signed in to change notification settings - Fork 0
/
ogtag.py
106 lines (84 loc) · 3.17 KB
/
ogtag.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"""Automatically generates Open Graph tags for Sphinx html docs.
Based on https://sphinx-users.jp/cookbook/ogp/index.html
"""
from docutils import nodes
from sphinx import addnodes
from urllib.parse import urljoin
class Visitor:
def __init__(self, document):
self.document = document
self.text_list = []
self.images = []
self.n_sections = 0
def dispatch_visit(self, node):
# Skip toctree
if isinstance(node, addnodes.compact_paragraph) and node.get("toctree"):
raise nodes.SkipChildren
# Collect images
if isinstance(node, nodes.image):
self.images.append(node)
# Collect text (first three sections)
if self.n_sections < 3:
# Collect paragraphs
if isinstance(node, nodes.paragraph):
self.text_list.append(node.astext().replace("\n", " "))
# Include only paragraphs
if isinstance(node, nodes.section):
self.n_sections += 1
def dispatch_departure(self, node):
pass
def get_og_description(self):
# TODO: Find optimal length for description text
text = " ".join(self.text_list)
if len(text) > 200:
text = text[:197] + "..."
return text
def get_og_image_url(self, page_url):
# TODO: Check if picking first image makes sense
# TODO: Return fallback image if no image found on page
if self.images:
return urljoin(page_url, self.images[0]["uri"])
else:
return None
def get_og_tags(context, doctree, config):
# page_url
site_url = config.og_site_url
page_url = urljoin(site_url, context["pagename"] + context["file_suffix"])
# collection
visitor = Visitor(doctree)
doctree.walkabout(visitor)
# og:description
og_desc = visitor.get_og_description()
# og:image
og_image = visitor.get_og_image_url(page_url)
## OGP
tags = """
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="{cfg[og_twitter_site]}" />
<meta property="og:site_name" content="{ctx[shorttitle]}">
<meta property="og:title" content="{ctx[title]}">
<meta property="og:description" content="{desc}">
<meta property='og:url' content="{page_url}">
""".format(
ctx=context, desc=og_desc, page_url=page_url, cfg=config
)
# Add image if present, use default image if no image is found
if og_image:
tags += f'<meta property="og:image" content="{og_image}">'
elif config.og_fallback_image:
tags += f'<meta property="og:image" content="{config.og_fallback_image}">'
return tags
def html_page_context(app, pagename, templatename, context, doctree):
if not doctree:
return
context["metatags"] += get_og_tags(context, doctree, app.config)
def setup(app):
app.add_config_value("og_site_url", None, "html")
app.add_config_value("og_twitter_site", None, "html")
app.add_config_value("og_fallback_image", None, "html")
app.connect("html-page-context", html_page_context)
return {
"version": "0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}