Small HTML fixes and documentation updates.
[docutils.git] / docutils / docutils / writers / xhtml11 / __init__.py
blobfe105fee211466c9575e77f09a9608c9a39370dd
1 # .. coding: utf8
2 # :Author: Günter Milde <milde@users.berlios.de>
3 # :Revision: $Revision$
4 # :Date: $Date: 2005-06-28$
5 # :Copyright: © 2005, 2009 Günter Milde.
6 # :License: Released under the terms of the `2-Clause BSD license`_, in short:
8 # Copying and distribution of this file, with or without modification,
9 # are permitted in any medium without royalty provided the copyright
10 # notice and this notice are preserved.
11 # This file is offered as-is, without any warranty.
13 # .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
15 """
16 Strict eXtensible HyperText Markup Language (XHTML) document Writer.
18 This is a variant of Docutils' `html-base` writer.
19 The output conforms to the XHTML version 1.1 DTD.
20 """
22 __docformat__ = 'reStructuredText'
24 import os
25 import os.path
26 import re
28 import docutils
29 from docutils import frontend, nodes, utils, writers, languages
30 from docutils.writers import html_base
32 class Writer(html_base.Writer):
34 supported = ('html', 'html4', 'html4strict', 'html4css2',
35 'xhtml', 'xhtml1', 'xhtml1strict', 'xhtml11')
36 """Formats this writer supports."""
38 default_stylesheets = ['html-base.css', 'xhtml11.css']
39 default_stylesheet_dirs = ['.',
40 os.path.abspath(os.path.dirname(__file__)),
41 os.path.abspath(os.path.join(
42 os.path.dirname(os.path.dirname(__file__)), 'html_base'))
45 config_section = 'xhtml11 writer'
46 config_section_dependencies = ('writers', 'html writer')
48 settings_spec = frontend.filter_settings_spec(
49 html_base.Writer.settings_spec,
50 stylesheet_path = (
51 'Comma separated list of stylesheet paths. '
52 'Relative paths are expanded if a matching file is found in '
53 'the --stylesheet-dirs. With --link-stylesheet, '
54 'the path is rewritten relative to the output HTML file. '
55 'Default: "%s"' % ','.join(default_stylesheets),
56 ['--stylesheet-path'],
57 {'metavar': '<file[,file,...]>', 'overrides': 'stylesheet',
58 'validator': frontend.validate_comma_separated_list,
59 'default': default_stylesheets}),
60 stylesheet_dirs = (
61 'Comma-separated list of directories where stylesheets are found. '
62 'Used by --stylesheet-path when expanding relative path arguments. '
63 'Default: "%s"' % default_stylesheet_dirs,
64 ['--stylesheet-dirs'],
65 {'metavar': '<dir[,dir,...]>',
66 'validator': frontend.validate_comma_separated_list,
67 'default': default_stylesheet_dirs}),
68 math_output = ('Math output format, one of "MathML", "HTML", '
69 '"MathJax" or "LaTeX". Default: "MathML"',
70 ['--math-output'],
71 {'default': 'MathML'}),
72 xml_declaration = ('Prepend an XML declaration. '
73 'Default: True',
74 ['--xml-declaration'],
75 {'default': True, 'action': 'store_true',
76 'validator': frontend.validate_boolean}))
78 def __init__(self):
79 writers.Writer.__init__(self)
80 self.translator_class = HTMLTranslator
83 class HTMLTranslator(html_base.HTMLTranslator):
84 """
85 This writer generates XHTML 1.1
86 without formatting that interferes with a CSS stylesheet.
87 """
88 doctype = ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" '
89 '"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n')
90 doctype_mathml = (
91 '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" '
92 '"http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd">\n')
94 # there is no attribute "lang" in XHTML 1.1
95 lang_attribute = 'xml:lang' # changed from 'lang' in XHTML 1.0
96 head_prefix_template = ('<html xmlns="http://www.w3.org/1999/xhtml"'
97 ' xml:lang="%(lang)s">\n<head>\n')
100 # enumerated lists
101 # ----------------
102 # The 'start' attribute does not conform to HTML4/XHTML1 Strict
103 # (resurfaced in HTML5)
105 def visit_enumerated_list(self, node):
106 atts = {}
107 if 'start' in node:
108 atts['style'] = 'counter-reset: item %d;' % (node['start'] - 1)
109 classes = node.setdefault('classes', [])
110 if 'enumtype' in node:
111 classes.append(node['enumtype'])
112 if self.is_compactable(node):
113 classes.append('simple')
114 self.body.append(self.starttag(node, 'ol', **atts))
117 # <sup> and <sub> tags (possible with parsed-literal) are not allowed
118 # in <pre> --- use <span> ::
120 def visit_subscript(self, node):
121 if isinstance(node.parent, nodes.literal_block):
122 self.body.append(self.starttag(node, 'span', '',
123 CLASS='subscript'))
124 else:
125 self.body.append(self.starttag(node, 'sub', ''))
127 def depart_subscript(self, node):
128 if isinstance(node.parent, nodes.literal_block):
129 self.body.append('</span>')
130 else:
131 self.body.append('</sub>')
134 def visit_superscript(self, node):
135 # <sup> not allowed in <pre>
136 if isinstance(node.parent, nodes.literal_block):
137 self.body.append(self.starttag(node, 'span', '',
138 CLASS='superscript'))
139 else:
140 self.body.append(self.starttag(node, 'sup', ''))
142 def depart_superscript(self, node):
143 if isinstance(node.parent, nodes.literal_block):
144 self.body.append('</span>')
145 else:
146 self.body.append('</sup>')
148 # Meta tags: 'lang' attribute replaced by 'xml:lang' in XHTML 1.1
149 # HTML5/polyglott recommends using both
151 def visit_meta(self, node):
152 if node.hasattr('lang'):
153 node['xml:lang'] = node['lang']
154 del(node['lang'])
155 meta = self.emptytag(node, 'meta', **node.non_default_attributes())
156 self.add_meta(meta)