2 # :Author: Günter Milde <milde@users.sf.net>
3 # Based on the html4css1 writer by David Goodger.
4 # :Maintainer: docutils-develop@lists.sourceforge.net
5 # :Revision: $Revision$
6 # :Date: $Date: 2005-06-28$
7 # :Copyright: © 2005, 2009, 2015 Günter Milde,
8 # portions from html4css1 © David Goodger.
9 # :License: Released under the terms of the `2-Clause BSD license`_, in short:
11 # Copying and distribution of this file, with or without modification,
12 # are permitted in any medium without royalty provided the copyright
13 # notice and this notice are preserved.
14 # This file is offered as-is, without any warranty.
16 # .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
18 # Use "best practice" as recommended by the W3C:
19 # http://www.w3.org/2009/cheatsheet/
22 Plain HyperText Markup Language document tree Writer.
24 The output conforms to the `HTML 5` specification.
26 The cascading style sheet "minimal.css" is required for proper viewing,
27 the style sheet "plain.css" improves reading experience.
29 __docformat__
= 'reStructuredText'
33 from docutils
import frontend
, nodes
, writers
, io
34 from docutils
.transforms
import writer_aux
35 from docutils
.writers
import _html_base
37 class Writer(writers
._html
_base
.Writer
):
39 supported
= ('html', 'html5', 'html4', 'xhtml', 'xhtml10')
40 """Formats this writer supports."""
42 default_stylesheets
= ['minimal.css','plain.css']
43 default_stylesheet_dirs
= ['.', os
.path
.abspath(os
.path
.dirname(__file__
))]
45 default_template
= 'template.txt'
46 default_template_path
= os
.path
.join(
47 os
.path
.dirname(os
.path
.abspath(__file__
)), default_template
)
50 'HTML-Specific Options',
52 (('Specify the template file (UTF-8 encoded). Default is "%s".'
53 % default_template_path
,
55 {'default': default_template_path
, 'metavar': '<file>'}),
56 ('Comma separated list of stylesheet URLs. '
57 'Overrides previous --stylesheet and --stylesheet-path settings.',
59 {'metavar': '<URL[,URL,...]>', 'overrides': 'stylesheet_path',
60 'validator': frontend
.validate_comma_separated_list
}),
61 ('Comma separated list of stylesheet paths. '
62 'Relative paths are expanded if a matching file is found in '
63 'the --stylesheet-dirs. With --link-stylesheet, '
64 'the path is rewritten relative to the output HTML file. '
65 'Default: "%s"' % ','.join(default_stylesheets
),
66 ['--stylesheet-path'],
67 {'metavar': '<file[,file,...]>', 'overrides': 'stylesheet',
68 'validator': frontend
.validate_comma_separated_list
,
69 'default': default_stylesheets
}),
70 ('Embed the stylesheet(s) in the output HTML file. The stylesheet '
71 'files must be accessible during processing. This is the default.',
72 ['--embed-stylesheet'],
73 {'default': 1, 'action': 'store_true',
74 'validator': frontend
.validate_boolean
}),
75 ('Link to the stylesheet(s) in the output HTML file. '
76 'Default: embed stylesheets.',
77 ['--link-stylesheet'],
78 {'dest': 'embed_stylesheet', 'action': 'store_false'}),
79 ('Comma-separated list of directories where stylesheets are found. '
80 'Used by --stylesheet-path when expanding relative path arguments. '
81 'Default: "%s"' % default_stylesheet_dirs
,
82 ['--stylesheet-dirs'],
83 {'metavar': '<dir[,dir,...]>',
84 'validator': frontend
.validate_comma_separated_list
,
85 'default': default_stylesheet_dirs
}),
86 ('Specify the initial header level. Default is 1 for "<h1>". '
87 'Does not affect document title & subtitle (see --no-doc-title).',
88 ['--initial-header-level'],
89 {'choices': '1 2 3 4 5 6'.split(), 'default': '1',
90 'metavar': '<level>'}),
91 ('Format for footnote references: one of "superscript" or '
92 '"brackets". Default is "brackets".',
93 ['--footnote-references'],
94 {'choices': ['superscript', 'brackets'], 'default': 'brackets',
95 'metavar': '<format>',
96 'overrides': 'trim_footnote_reference_space'}),
97 ('Format for block quote attributions: one of "dash" (em-dash '
98 'prefix), "parentheses"/"parens", or "none". Default is "dash".',
100 {'choices': ['dash', 'parentheses', 'parens', 'none'],
101 'default': 'dash', 'metavar': '<format>'}),
102 ('Remove extra vertical whitespace between items of "simple" bullet '
103 'lists and enumerated lists. Default: enabled.',
105 {'default': True, 'action': 'store_true',
106 'validator': frontend
.validate_boolean
}),
107 ('Disable compact simple bullet and enumerated lists.',
108 ['--no-compact-lists'],
109 {'dest': 'compact_lists', 'action': 'store_false'}),
110 ('Remove extra vertical whitespace between items of simple field '
111 'lists. Default: enabled.',
112 ['--compact-field-lists'],
113 {'default': True, 'action': 'store_true',
114 'validator': frontend
.validate_boolean
}),
115 ('Disable compact simple field lists.',
116 ['--no-compact-field-lists'],
117 {'dest': 'compact_field_lists', 'action': 'store_false'}),
118 ('Added to standard table classes. '
119 'Defined styles: borderless, booktabs, '
120 'align-left, align-center, align-right, colwidths-auto. '
124 ('Math output format (one of "MathML", "HTML", "MathJax", '
125 'or "LaTeX") and option(s). '
126 'Default: "HTML math.css"',
128 {'default': 'HTML math.css'}),
129 ('Prepend an XML declaration. (Thwarts HTML5 conformance.) '
131 ['--xml-declaration'],
132 {'default': False, 'action': 'store_true',
133 'validator': frontend
.validate_boolean
}),
134 ('Omit the XML declaration.',
135 ['--no-xml-declaration'],
136 {'dest': 'xml_declaration', 'action': 'store_false'}),
137 ('Obfuscate email addresses to confuse harvesters while still '
138 'keeping email links usable with standards-compliant browsers.',
139 ['--cloak-email-addresses'],
140 {'action': 'store_true', 'validator': frontend
.validate_boolean
}),))
142 config_section
= 'html-plain writer'
146 self
.translator_class
= HTMLTranslator
149 class HTMLTranslator(writers
._html
_base
.HTMLTranslator
):
151 This writer generates `polyglot markup`: HTML 5 that is also valid XML.
153 # def __init__(self, document):
154 # writers._html_base.HTMLTranslator.__init__(self, document)
157 # <acronym> tag not supported in HTML5. Use the <abbr> tag instead.
158 def visit_acronym(self
, node
):
159 # @@@ implementation incomplete ("title" attribute)
160 self
.body
.append(self
.starttag(node
, 'abbr', ''))
162 def depart_acronym(self
, node
):
163 self
.body
.append('</abbr>')
165 # no meta tag in HTML 5
166 def visit_authors(self
, node
):
167 self
.visit_docinfo_item(node
, 'authors', meta
=False)
169 def visit_copyright(self
, node
):
170 self
.visit_docinfo_item(node
, 'copyright', meta
=False)
172 # no meta tag in HTML 5
173 def visit_date(self
, node
):
174 self
.visit_docinfo_item(node
, 'date', meta
=False)
176 # TODO: use HTML 5 <footer> element?
177 # def visit_footer(self, node):
178 # def depart_footer(self, node):
180 # TODO: use the new HTML5 element <aside>? (Also for footnote text)
181 # def visit_footnote(self, node):
183 # Meta tags: 'lang' attribute replaced by 'xml:lang' in XHTML 1.1
184 # HTML5/polyglot recommends using both
185 def visit_meta(self
, node
):
186 if node
.hasattr('lang'):
187 node
['xml:lang'] = node
['lang']
189 meta
= self
.emptytag(node
, 'meta', **node
.non_default_attributes())
192 # no meta tag in HTML 5
193 def visit_organization(self
, node
):
194 self
.visit_docinfo_item(node
, 'organization', meta
=False)
196 # TODO: use the new HTML 5 element <section>?
197 # def visit_section(self, node):
199 # TODO: use the new HTML5 element <aside>?
200 # def visit_topic(self, node):