__init__.py (6351B)
1 """Sphinx Guzzle theme.""" 2 3 import os 4 from os import path 5 import xml.etree.ElementTree as ET 6 7 from docutils import nodes 8 from sphinx.locale import admonitionlabels 9 from sphinx.writers.html import HTMLTranslator as SphinxHTMLTranslator 10 11 from pygments.style import Style 12 from pygments.token import Keyword, Name, Comment, String, Error, \ 13 Number, Operator, Generic, Whitespace, Punctuation, Other, Literal 14 15 16 def 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 26 def 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 33 def 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 53 def html_theme_path(): 54 return [os.path.dirname(os.path.abspath(__file__))] 55 56 57 class 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)