forked from godotengine/godot-docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgodot_descriptions.py
120 lines (89 loc) · 3.45 KB
/
godot_descriptions.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# -*- coding: utf-8 -*-
"""
godot_descriptions
~~~~~~~~~~~~~~~~~~
Sphinx extension to automatically generate HTML meta description tags
for all pages. Also comes with some special support for Godot class docs.
:copyright: Copyright 2021 by The Godot Engine Community
:license: MIT.
based on the work of Takayuki Shimizukawa on OpenGraph support for Sphinx,
see: https://github.com/sphinx-contrib/ogp
"""
import re
from docutils import nodes
from sphinx import addnodes
class DescriptionGenerator:
def __init__(self, document, pagename="", n_sections_max=3, max_length=220):
self.document = document
self.text_list = []
self.max_length = max_length
self.current_length = 0
self.n_sections = 0
self.n_sections_max = n_sections_max
self.pagename = pagename
self.is_class = pagename.startswith("classes/")
self.stop_word_reached = False
def dispatch_visit(self, node):
if (
self.stop_word_reached
or self.current_length > self.max_length
or self.n_sections > self.n_sections_max
):
return
if isinstance(node, addnodes.compact_paragraph) and node.get("toctree"):
raise nodes.SkipChildren
add = True
if isinstance(node, nodes.paragraph):
text = node.astext()
if self.is_class:
# Skip OOP hierarchy info for description
if (
text.startswith("Inherits:")
or text.startswith("Inherited By:")
or text.strip() == "Example:"
):
add = False
# If we're in a class doc and reached the first table,
# stop adding to the description
if text.strip() == "Properties":
self.stop_word_reached = True
add = False
if add:
self.text_list.append(text)
self.current_length = self.current_length + len(text)
if add and isinstance(node, nodes.section):
self.n_sections += 1
def dispatch_departure(self, node):
pass
def format_description(self, desc):
# Replace newlines with spaces
desc = re.sub("\r|\n", " ", desc)
# Replace multiple spaces with single spaces
desc = re.sub("\\s+", " ", desc)
# Escape double quotes for HTML
desc = re.sub('"', """, desc)
return desc
def create_description(self, cutoff_suffix="..."):
text = " ".join(self.text_list)
text = self.format_description(text)
# Cut to self.max_length, add cutoff_suffix at end
if len(text) > self.max_length:
text = text[: self.max_length - len(cutoff_suffix)].strip() + cutoff_suffix
return text
def generate_description(app, pagename, templatename, context, doctree):
if not doctree:
return
generator = DescriptionGenerator(doctree, pagename)
doctree.walkabout(generator)
description = (
'<meta name="description" content="' + generator.create_description() + '">\n'
)
context["metatags"] += description
def setup(app):
# Hook into Sphinx for all pages to
# generate meta description tag and add to meta tag list
app.connect("html-page-context", generate_description)
return {
"parallel_read_safe": True,
"parallel_write_safe": True,
}