aboutsummaryrefslogtreecommitdiff
path: root/doc/sphinx/_exts/taler_sphinx_theme/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'doc/sphinx/_exts/taler_sphinx_theme/__init__.py')
-rw-r--r--doc/sphinx/_exts/taler_sphinx_theme/__init__.py166
1 files changed, 166 insertions, 0 deletions
diff --git a/doc/sphinx/_exts/taler_sphinx_theme/__init__.py b/doc/sphinx/_exts/taler_sphinx_theme/__init__.py
new file mode 100644
index 0000000..2d3c61c
--- /dev/null
+++ b/doc/sphinx/_exts/taler_sphinx_theme/__init__.py
@@ -0,0 +1,166 @@
1"""Sphinx Guzzle theme."""
2
3import os
4from os import path
5import xml.etree.ElementTree as ET
6
7from docutils import nodes
8from sphinx.locale import admonitionlabels
9from sphinx.writers.html import HTMLTranslator as SphinxHTMLTranslator
10
11from pygments.style import Style
12from pygments.token import Keyword, Name, Comment, String, Error, \
13 Number, Operator, Generic, Whitespace, Punctuation, Other, Literal
14
15
16def setup(app):
17 """Setup conntects events to the sitemap builder"""
18 app.connect('html-page-context', add_html_link)
19 app.connect('build-finished', create_sitemap)
20 app.set_translator('html', MyHTMLTranslator)
21 app.set_translator('html-linked', MyHTMLTranslator)
22 app.sitemap_links = []
23 app.add_html_theme('taler_sphinx_theme', path.abspath(path.dirname(__file__) + "/guzzle_sphinx_theme"))
24
25
26def add_html_link(app, pagename, templatename, context, doctree):
27 """As each page is built, collect page names for the sitemap"""
28 base_url = app.config['html_theme_options'].get('base_url', '')
29 if base_url:
30 app.sitemap_links.append(base_url + pagename + ".html")
31
32
33def create_sitemap(app, exception):
34 """Generates the sitemap.xml from the collected HTML page links"""
35 if (not app.config['html_theme_options'].get('base_url', '') or
36 exception is not None or
37 not app.sitemap_links):
38 return
39
40 filename = app.outdir + "/sitemap.xml"
41 print("Generating sitemap.xml in %s" % filename)
42
43 root = ET.Element("urlset")
44 root.set("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9")
45
46 for link in app.sitemap_links:
47 url = ET.SubElement(root, "url")
48 ET.SubElement(url, "loc").text = link
49
50 ET.ElementTree(root).write(filename)
51
52
53def html_theme_path():
54 return [os.path.dirname(os.path.abspath(__file__))]
55
56
57class MyHTMLTranslator(SphinxHTMLTranslator):
58 """
59 Handle translating to bootstrap structure.
60 """
61 def visit_table(self, node, name=''):
62 """
63 Override docutils default table formatter to not include a border
64 and to use Bootstrap CSS
65 See: http://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/docutils/writers/html4css1/__init__.py#l1550
66 """
67 self.context.append(self.compact_p)
68 self.compact_p = True
69 classes = 'table table-bordered ' + self.settings.table_style
70 classes = classes.strip()
71 self.body.append(
72 self.starttag(node, 'table', CLASS=classes))
73
74 def depart_table(self, node):
75 """
76 This needs overridin' too
77 """
78 self.compact_p = self.context.pop()
79 self.body.append('</table>\n')
80
81 def visit_field(self, node):
82 pass
83
84 def depart_field(self, node):
85 pass
86
87 def visit_field_name(self, node):
88 atts = {}
89 if self.in_docinfo:
90 atts['class'] = 'docinfo-name'
91 else:
92 atts['class'] = 'field-name'
93 self.context.append('')
94 self.body.append(self.starttag(node, 'dt', '', **atts))
95
96 def depart_field_name(self, node):
97 self.body.append('</dt>')
98 self.body.append(self.context.pop())
99
100 def visit_field_body(self, node):
101 self.body.append(self.starttag(node, 'dd', '', CLASS='field-body'))
102 self.set_class_on_child(node, 'first', 0)
103 field = node.parent
104 if (self.compact_field_list or
105 isinstance(field.parent, nodes.docinfo) or
106 field.parent.index(field) == len(field.parent) - 1):
107 # If we are in a compact list, the docinfo, or if this is
108 # the last field of the field list, do not add vertical
109 # space after last element.
110 self.set_class_on_child(node, 'last', -1)
111
112 def depart_field_body(self, node):
113 self.body.append('</dd>\n')
114
115 def visit_field_list(self, node):
116 self.context.append((self.compact_field_list, self.compact_p))
117 self.compact_p = None
118 if 'compact' in node['classes']:
119 self.compact_field_list = True
120 elif (self.settings.compact_field_lists
121 and 'open' not in node['classes']):
122 self.compact_field_list = True
123 if self.compact_field_list:
124 for field in node:
125 field_body = field[-1]
126 assert isinstance(field_body, nodes.field_body)
127 children = [n for n in field_body
128 if not isinstance(n, nodes.Invisible)]
129 if not (len(children) == 0 or
130 len(children) == 1 and
131 isinstance(children[0],
132 (nodes.paragraph, nodes.line_block))):
133 self.compact_field_list = False
134 break
135 self.body.append(self.starttag(node, 'dl', frame='void',
136 rules='none',
137 CLASS='docutils field-list'))
138
139 def depart_field_list(self, node):
140 self.body.append('</dl>\n')
141 self.compact_field_list, self.compact_p = self.context.pop()
142
143 def visit_container(self, node):
144 self.body.append(self.starttag(node, 'div', CLASS='docutils'))
145
146 def add_secnumber(self, node):
147 # type: (nodes.Element) -> None
148 if node.get('secnumber'):
149 numbers = list(map(str, node['secnumber']))
150 if len(numbers) <= 3:
151 self.body.append('.'.join(numbers) + self.secnumber_suffix)
152 elif isinstance(node.parent, nodes.section):
153 if self.builder.name == 'singlehtml':
154 docname = self.docnames[-1]
155 anchorname = "%s/#%s" % (docname, node.parent['ids'][0])
156 if anchorname not in self.builder.secnumbers:
157 anchorname = "%s/" % docname # try first heading which has no anchor
158 else:
159 anchorname = '#' + node.parent['ids'][0]
160 if anchorname not in self.builder.secnumbers:
161 anchorname = '' # try first heading which has no anchor
162 if self.builder.secnumbers.get(anchorname):
163 numbers = list(self.builder.secnumbers[anchorname])
164 if len(numbers) <= 3:
165 self.body.append('.'.join(map(str, numbers)) +
166 self.secnumber_suffix)