"""
Html5 writer
============
Original code is from 'Bradley Wright' on Github :
https://github.com/bradleywright/rst-to-semantic-html5
Stealed and modified because i wanted to keep ``<section/>`` behavior but not
to follow the same way than 'rst-to-semantic-html5'.
"""
import re
from docutils import nodes, utils
from docutils.writers import html4css1
from docutils.parsers.rst import roles
[docs]class SemanticHTML5Writer(html4css1.Writer):
"""
This docutils writer will use the SemanticHTML5Translator class below.
"""
def __init__(self):
html4css1.Writer.__init__(self)
self.translator_class = SemanticHTML5Translator
[docs]class SemanticHTML5Translator(html4css1.HTMLTranslator):
"""
This is a translator class for the docutils system.
It will produce a minimal set of html output.
(No extra divs, classes over ids.)
It also aims to produce HTML5 (section etc.)
"""
def should_be_compact_paragraph(self, node):
if(isinstance(node.parent, nodes.block_quote)):
return 0
return html4css1.HTMLTranslator.should_be_compact_paragraph(self, node)
def visit_section(self, node):
self.section_level += 1
self.body.append(self.starttag(node, 'section', ''))
def depart_section(self, node):
self.section_level -= 1
self.body.append('</section>')
[docs] def visit_literal_block(self, node):
"No classes please"
self.body.append(self.starttag(node, 'pre', ''))
def visit_literal(self, node):
self.body.append(
self.starttag(node, 'code', ''))
def depart_literal(self, node):
self.body.append('</code>')
def visit_abbreviation(self, node):
attrs = {}
if node.hasattr('explanation'):
attrs['title'] = node['explanation']
self.body.append(self.starttag(node, 'abbr', '', **attrs))
def depart_abbreviation(self, node):
self.body.append('</abbr>')
def visit_kbd(self, node):
self.body.append(self.starttag(node, 'kbd', ''))
def depart_kbd(self, node):
self.body.append('</kbd>')
[docs]class kbd(nodes.Inline, nodes.TextElement):
"""Node for kbd element"""
nodes._add_node_class_names('kbd')
def inline_roles(role, raw, text, *args):
if role == 'kbd':
return [kbd('kbd', text)], []
elif role == 'var':
return [nodes.literal('var', text)], []
roles.register_local_role('kbd', inline_roles)
roles.register_local_role('var', inline_roles)
# Node plugin name have to be lowercase for some reasons from docutils
[docs]class abbreviation(nodes.Inline, nodes.TextElement):
"""Node for abbreviations with explanations."""
nodes._add_node_class_names('abbreviation')
_abbr_re = re.compile('\((.*)\)$', re.S)
def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
text = utils.unescape(text)
m = _abbr_re.search(text)
if m is None:
return [abbreviation(text, text)], []
abbr = text[:m.start()].strip()
expl = m.group(1)
return [abbreviation(abbr, abbr, explanation=expl)], []
roles.register_local_role('abbr', abbr_role)