first commit

This commit is contained in:
Yura 2024-09-15 15:12:16 +03:00
commit 417e54da96
5696 changed files with 900003 additions and 0 deletions

View file

@ -0,0 +1,159 @@
# $Id: __init__.py 9368 2023-04-28 21:26:36Z milde $
# Author: David Goodger <goodger@python.org>
# Copyright: This module has been placed in the public domain.
"""
This package contains Docutils Writer modules.
"""
__docformat__ = 'reStructuredText'
from importlib import import_module
import docutils
from docutils import languages, Component
from docutils.transforms import universal
class Writer(Component):
"""
Abstract base class for docutils Writers.
Each writer module or package must export a subclass also called 'Writer'.
Each writer must support all standard node types listed in
`docutils.nodes.node_class_names`.
The `write()` method is the main entry point.
"""
component_type = 'writer'
config_section = 'writers'
def get_transforms(self):
return super().get_transforms() + [universal.Messages,
universal.FilterMessages,
universal.StripClassesAndElements]
document = None
"""The document to write (Docutils doctree); set by `write()`."""
output = None
"""Final translated form of `document`
(`str` for text, `bytes` for binary formats); set by `translate()`.
"""
language = None
"""Language module for the document; set by `write()`."""
destination = None
"""`docutils.io` Output object; where to write the document.
Set by `write()`.
"""
def __init__(self):
self.parts = {}
"""Mapping of document part names to fragments of `self.output`.
See `Writer.assemble_parts()` below and
<https://docutils.sourceforge.io/docs/api/publisher.html>.
"""
def write(self, document, destination):
"""
Process a document into its final form.
Translate `document` (a Docutils document tree) into the Writer's
native format, and write it out to its `destination` (a
`docutils.io.Output` subclass object).
Normally not overridden or extended in subclasses.
"""
self.document = document
self.language = languages.get_language(
document.settings.language_code,
document.reporter)
self.destination = destination
self.translate()
return self.destination.write(self.output)
def translate(self):
"""
Do final translation of `self.document` into `self.output`. Called
from `write`. Override in subclasses.
Usually done with a `docutils.nodes.NodeVisitor` subclass, in
combination with a call to `docutils.nodes.Node.walk()` or
`docutils.nodes.Node.walkabout()`. The ``NodeVisitor`` subclass must
support all standard elements (listed in
`docutils.nodes.node_class_names`) and possibly non-standard elements
used by the current Reader as well.
"""
raise NotImplementedError('subclass must override this method')
def assemble_parts(self):
"""Assemble the `self.parts` dictionary. Extend in subclasses.
See <https://docutils.sourceforge.io/docs/api/publisher.html>.
"""
self.parts['whole'] = self.output
self.parts['encoding'] = self.document.settings.output_encoding
self.parts['errors'] = (
self.document.settings.output_encoding_error_handler)
self.parts['version'] = docutils.__version__
class UnfilteredWriter(Writer):
"""
A writer that passes the document tree on unchanged (e.g. a
serializer.)
Documents written by UnfilteredWriters are typically reused at a
later date using a subclass of `readers.ReReader`.
"""
def get_transforms(self):
# Do not add any transforms. When the document is reused
# later, the then-used writer will add the appropriate
# transforms.
return Component.get_transforms(self)
_writer_aliases = {
'html': 'html4css1', # may change to html5 some day
'html4': 'html4css1',
'xhtml10': 'html4css1',
'html5': 'html5_polyglot',
'xhtml': 'html5_polyglot',
's5': 's5_html',
'latex': 'latex2e',
'xelatex': 'xetex',
'luatex': 'xetex',
'lualatex': 'xetex',
'odf': 'odf_odt',
'odt': 'odf_odt',
'ooffice': 'odf_odt',
'openoffice': 'odf_odt',
'libreoffice': 'odf_odt',
'pprint': 'pseudoxml',
'pformat': 'pseudoxml',
'pdf': 'rlpdf',
'xml': 'docutils_xml'}
def get_writer_class(writer_name):
"""Return the Writer class from the `writer_name` module."""
name = writer_name.lower()
name = _writer_aliases.get(name, name)
try:
module = import_module('docutils.writers.'+name)
except ImportError:
try:
module = import_module(name)
except ImportError as err:
raise ImportError(f'Writer "{writer_name}" not found. {err}')
return module.Writer

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,187 @@
# $Id: docutils_xml.py 9502 2023-12-14 22:39:08Z milde $
# Author: David Goodger, Paul Tremblay, Guenter Milde
# Maintainer: docutils-develop@lists.sourceforge.net
# Copyright: This module has been placed in the public domain.
"""
Simple document tree Writer, writes Docutils XML according to
https://docutils.sourceforge.io/docs/ref/docutils.dtd.
"""
__docformat__ = 'reStructuredText'
from io import StringIO
import xml.sax.saxutils
import docutils
from docutils import frontend, nodes, writers, utils
class RawXmlError(docutils.ApplicationError):
pass
class Writer(writers.Writer):
supported = ('xml',)
"""Formats this writer supports."""
settings_spec = (
'"Docutils XML" Writer Options',
None,
(('Generate XML with newlines before and after tags.',
['--newlines'],
{'action': 'store_true', 'validator': frontend.validate_boolean}),
('Generate XML with indents and newlines.',
['--indents'], # TODO use integer value for number of spaces?
{'action': 'store_true', 'validator': frontend.validate_boolean}),
('Omit the XML declaration. Use with caution.',
['--no-xml-declaration'],
{'dest': 'xml_declaration', 'default': 1, 'action': 'store_false',
'validator': frontend.validate_boolean}),
('Omit the DOCTYPE declaration.',
['--no-doctype'],
{'dest': 'doctype_declaration', 'default': 1,
'action': 'store_false', 'validator': frontend.validate_boolean}),))
settings_defaults = {'output_encoding_error_handler': 'xmlcharrefreplace'}
config_section = 'docutils_xml writer'
config_section_dependencies = ('writers',)
output = None
"""Final translated form of `document`."""
def __init__(self):
writers.Writer.__init__(self)
self.translator_class = XMLTranslator
def translate(self):
self.visitor = visitor = self.translator_class(self.document)
self.document.walkabout(visitor)
self.output = ''.join(visitor.output)
class XMLTranslator(nodes.GenericNodeVisitor):
# TODO: add stylesheet options similar to HTML and LaTeX writers?
# xml_stylesheet = '<?xml-stylesheet type="text/xsl" href="%s"?>\n'
doctype = (
'<!DOCTYPE document PUBLIC'
' "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML"'
' "http://docutils.sourceforge.net/docs/ref/docutils.dtd">\n')
generator = '<!-- Generated by Docutils %s -->\n'
xmlparser = xml.sax.make_parser()
"""SAX parser instance to check/extract raw XML."""
xmlparser.setFeature(
"http://xml.org/sax/features/external-general-entities", True)
def __init__(self, document):
nodes.NodeVisitor.__init__(self, document)
# Reporter
self.warn = self.document.reporter.warning
self.error = self.document.reporter.error
# Settings
self.settings = settings = document.settings
self.indent = self.newline = ''
if settings.newlines:
self.newline = '\n'
if settings.indents:
self.newline = '\n'
self.indent = ' ' # TODO make this configurable?
self.level = 0 # indentation level
self.in_simple = 0 # level of nesting inside mixed-content elements
self.fixed_text = 0 # level of nesting inside FixedText elements
# Output
self.output = []
if settings.xml_declaration:
self.output.append(utils.xml_declaration(settings.output_encoding))
if settings.doctype_declaration:
self.output.append(self.doctype)
self.output.append(self.generator % docutils.__version__)
# initialize XML parser
self.the_handle = TestXml()
self.xmlparser.setContentHandler(self.the_handle)
# generic visit and depart methods
# --------------------------------
simple_nodes = (nodes.TextElement, nodes.meta,
nodes.image, nodes.colspec, nodes.transition)
def default_visit(self, node):
"""Default node visit method."""
if not self.in_simple:
self.output.append(self.indent*self.level)
self.output.append(node.starttag(xml.sax.saxutils.quoteattr))
self.level += 1
# `nodes.literal` is not an instance of FixedTextElement by design,
# see docs/ref/rst/restructuredtext.html#inline-literals
if isinstance(node, (nodes.FixedTextElement, nodes.literal)):
self.fixed_text += 1
if isinstance(node, self.simple_nodes):
self.in_simple += 1
if not self.in_simple:
self.output.append(self.newline)
def default_departure(self, node):
"""Default node depart method."""
self.level -= 1
if not self.in_simple:
self.output.append(self.indent*self.level)
self.output.append(node.endtag())
if isinstance(node, (nodes.FixedTextElement, nodes.literal)):
self.fixed_text -= 1
if isinstance(node, self.simple_nodes):
self.in_simple -= 1
if not self.in_simple:
self.output.append(self.newline)
# specific visit and depart methods
# ---------------------------------
def visit_Text(self, node):
text = xml.sax.saxutils.escape(node.astext())
# indent text if we are not in a FixedText element:
if not self.fixed_text:
text = text.replace('\n', '\n'+self.indent*self.level)
self.output.append(text)
def depart_Text(self, node):
pass
def visit_raw(self, node):
if 'xml' not in node.get('format', '').split():
# skip other raw content?
# raise nodes.SkipNode
self.default_visit(node)
return
# wrap in <raw> element
self.default_visit(node) # or not?
xml_string = node.astext()
self.output.append(xml_string)
self.default_departure(node) # or not?
# Check validity of raw XML:
try:
self.xmlparser.parse(StringIO(xml_string))
except xml.sax._exceptions.SAXParseException:
col_num = self.the_handle.locator.getColumnNumber()
line_num = self.the_handle.locator.getLineNumber()
srcline = node.line
if not isinstance(node.parent, nodes.TextElement):
srcline += 2 # directive content start line
msg = 'Invalid raw XML in column %d, line offset %d:\n%s' % (
col_num, line_num, node.astext())
self.warn(msg, source=node.source, line=srcline+line_num-1)
raise nodes.SkipNode # content already processed
class TestXml(xml.sax.handler.ContentHandler):
def setDocumentLocator(self, locator):
self.locator = locator

View file

@ -0,0 +1,955 @@
# $Id: __init__.py 9558 2024-03-11 17:48:52Z milde $
# Author: David Goodger
# Maintainer: docutils-develop@lists.sourceforge.net
# Copyright: This module has been placed in the public domain.
"""
Simple HyperText Markup Language document tree Writer.
The output conforms to the XHTML version 1.0 Transitional DTD
(*almost* strict). The output contains a minimum of formatting
information. The cascading style sheet "html4css1.css" is required
for proper viewing with a modern graphical browser.
"""
__docformat__ = 'reStructuredText'
import os.path
import re
from docutils import frontend, nodes, writers
from docutils.writers import _html_base
from docutils.writers._html_base import PIL
class Writer(writers._html_base.Writer):
supported = ('html', 'html4', 'html4css1', 'xhtml', 'xhtml10')
"""Formats this writer supports."""
default_stylesheets = ['html4css1.css']
default_stylesheet_dirs = ['.',
os.path.abspath(os.path.dirname(__file__)),
os.path.abspath(os.path.join(
os.path.dirname(os.path.dirname(__file__)),
'html5_polyglot')) # for math.css
]
default_template = os.path.join(
os.path.dirname(os.path.abspath(__file__)), 'template.txt')
# use a copy of the parent spec with some modifications
settings_spec = frontend.filter_settings_spec(
writers._html_base.Writer.settings_spec,
template=(
'Template file. (UTF-8 encoded, default: "%s")' % default_template,
['--template'],
{'default': default_template, 'metavar': '<file>'}),
stylesheet_path=(
'Comma separated list of stylesheet paths. '
'Relative paths are expanded if a matching file is found in '
'the --stylesheet-dirs. With --link-stylesheet, '
'the path is rewritten relative to the output HTML file. '
'(default: "%s")' % ','.join(default_stylesheets),
['--stylesheet-path'],
{'metavar': '<file[,file,...]>', 'overrides': 'stylesheet',
'validator': frontend.validate_comma_separated_list,
'default': default_stylesheets}),
stylesheet_dirs=(
'Comma-separated list of directories where stylesheets are found. '
'Used by --stylesheet-path when expanding relative path '
'arguments. (default: "%s")' % ','.join(default_stylesheet_dirs),
['--stylesheet-dirs'],
{'metavar': '<dir[,dir,...]>',
'validator': frontend.validate_comma_separated_list,
'default': default_stylesheet_dirs}),
initial_header_level=(
'Specify the initial header level. Does not affect document '
'title & subtitle (see --no-doc-title). (default: 1 for "<h1>")',
['--initial-header-level'],
{'choices': '1 2 3 4 5 6'.split(), 'default': '1',
'metavar': '<level>'}),
xml_declaration=(
'Prepend an XML declaration (default). ',
['--xml-declaration'],
{'default': True, 'action': 'store_true',
'validator': frontend.validate_boolean}),
)
settings_spec = settings_spec + (
'HTML4 Writer Options',
'',
(('Specify the maximum width (in characters) for one-column field '
'names. Longer field names will span an entire row of the table '
'used to render the field list. Default is 14 characters. '
'Use 0 for "no limit".',
['--field-name-limit'],
{'default': 14, 'metavar': '<level>',
'validator': frontend.validate_nonnegative_int}),
('Specify the maximum width (in characters) for options in option '
'lists. Longer options will span an entire row of the table used '
'to render the option list. Default is 14 characters. '
'Use 0 for "no limit".',
['--option-limit'],
{'default': 14, 'metavar': '<level>',
'validator': frontend.validate_nonnegative_int}),
)
)
config_section = 'html4css1 writer'
def __init__(self):
self.parts = {}
self.translator_class = HTMLTranslator
class HTMLTranslator(writers._html_base.HTMLTranslator):
"""
The html4css1 writer has been optimized to produce visually compact
lists (less vertical whitespace). HTML's mixed content models
allow list items to contain "<li><p>body elements</p></li>" or
"<li>just text</li>" or even "<li>text<p>and body
elements</p>combined</li>", each with different effects. It would
be best to stick with strict body elements in list items, but they
affect vertical spacing in older browsers (although they really
shouldn't).
The html5_polyglot writer solves this using CSS2.
Here is an outline of the optimization:
- Check for and omit <p> tags in "simple" lists: list items
contain either a single paragraph, a nested simple list, or a
paragraph followed by a nested simple list. This means that
this list can be compact:
- Item 1.
- Item 2.
But this list cannot be compact:
- Item 1.
This second paragraph forces space between list items.
- Item 2.
- In non-list contexts, omit <p> tags on a paragraph if that
paragraph is the only child of its parent (footnotes & citations
are allowed a label first).
- Regardless of the above, in definitions, table cells, field bodies,
option descriptions, and list items, mark the first child with
'class="first"' and the last child with 'class="last"'. The stylesheet
sets the margins (top & bottom respectively) to 0 for these elements.
The ``no_compact_lists`` setting (``--no-compact-lists`` command-line
option) disables list whitespace optimization.
"""
# The following definitions are required for display in browsers limited
# to CSS1 or backwards compatible behaviour of the writer:
doctype = (
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n')
content_type = ('<meta http-equiv="Content-Type"'
' content="text/html; charset=%s" />\n')
content_type_mathml = ('<meta http-equiv="Content-Type"'
' content="application/xhtml+xml; charset=%s" />\n')
# encode also non-breaking space
special_characters = _html_base.HTMLTranslator.special_characters.copy()
special_characters[0xa0] = '&nbsp;'
# use character reference for dash (not valid in HTML5)
attribution_formats = {'dash': ('&mdash;', ''),
'parentheses': ('(', ')'),
'parens': ('(', ')'),
'none': ('', '')}
# ersatz for first/last pseudo-classes missing in CSS1
def set_first_last(self, node):
self.set_class_on_child(node, 'first', 0)
self.set_class_on_child(node, 'last', -1)
# add newline after opening tag
def visit_address(self, node):
self.visit_docinfo_item(node, 'address', meta=False)
self.body.append(self.starttag(node, 'pre', CLASS='address'))
def depart_address(self, node):
self.body.append('\n</pre>\n')
self.depart_docinfo_item()
# ersatz for first/last pseudo-classes
def visit_admonition(self, node):
node['classes'].insert(0, 'admonition')
self.body.append(self.starttag(node, 'div'))
self.set_first_last(node)
def depart_admonition(self, node=None):
self.body.append('</div>\n')
# author, authors: use <br> instead of paragraphs
def visit_author(self, node):
if isinstance(node.parent, nodes.authors):
if self.author_in_authors:
self.body.append('\n<br />')
else:
self.visit_docinfo_item(node, 'author')
def depart_author(self, node):
if isinstance(node.parent, nodes.authors):
self.author_in_authors = True
else:
self.depart_docinfo_item()
def visit_authors(self, node):
self.visit_docinfo_item(node, 'authors')
self.author_in_authors = False # initialize
def depart_authors(self, node):
self.depart_docinfo_item()
# use "width" argument instead of "style: 'width'":
def visit_colspec(self, node):
self.colspecs.append(node)
# "stubs" list is an attribute of the tgroup element:
node.parent.stubs.append(node.attributes.get('stub'))
def depart_colspec(self, node):
# write out <colgroup> when all colspecs are processed
if isinstance(node.next_node(descend=False, siblings=True),
nodes.colspec):
return
if ('colwidths-auto' in node.parent.parent['classes']
or ('colwidths-auto' in self.settings.table_style
and 'colwidths-given' not in node.parent.parent['classes'])):
return
total_width = sum(node['colwidth'] for node in self.colspecs)
self.body.append(self.starttag(node, 'colgroup'))
for node in self.colspecs:
colwidth = int(node['colwidth'] * 100.0 / total_width + 0.5)
self.body.append(self.emptytag(node, 'col',
width='%i%%' % colwidth))
self.body.append('</colgroup>\n')
# Compact lists:
# exclude definition lists and field lists (non-compact by default)
def is_compactable(self, node):
return ('compact' in node['classes']
or (self.settings.compact_lists
and 'open' not in node['classes']
and (self.compact_simple
or 'contents' in node.parent['classes']
# TODO: self.in_contents
or self.check_simple_list(node))))
# citations: Use table for bibliographic references.
def visit_citation(self, node):
self.body.append(self.starttag(node, 'table',
CLASS='docutils citation',
frame="void", rules="none"))
self.body.append('<colgroup><col class="label" /><col /></colgroup>\n'
'<tbody valign="top">\n'
'<tr>')
self.footnote_backrefs(node)
def depart_citation(self, node):
self.body.append('</td></tr>\n'
'</tbody>\n</table>\n')
def visit_citation_reference(self, node):
href = '#'
if 'refid' in node:
href += node['refid']
elif 'refname' in node:
href += self.document.nameids[node['refname']]
self.body.append(self.starttag(node, 'a', suffix='[', href=href,
classes=['citation-reference']))
def depart_citation_reference(self, node):
self.body.append(']</a>')
# insert classifier-delimiter (not required with CSS2)
def visit_classifier(self, node):
self.body.append(' <span class="classifier-delimiter">:</span> ')
self.body.append(self.starttag(node, 'span', '', CLASS='classifier'))
def depart_classifier(self, node):
self.body.append('</span>')
self.depart_term(node) # close the <dt> after last classifier
# ersatz for first/last pseudo-classes
def visit_compound(self, node):
self.body.append(self.starttag(node, 'div', CLASS='compound'))
if len(node) > 1:
node[0]['classes'].append('compound-first')
node[-1]['classes'].append('compound-last')
for child in node[1:-1]:
child['classes'].append('compound-middle')
def depart_compound(self, node):
self.body.append('</div>\n')
# ersatz for first/last pseudo-classes, no special handling of "details"
def visit_definition(self, node):
self.body.append(self.starttag(node, 'dd', ''))
self.set_first_last(node)
def depart_definition(self, node):
self.body.append('</dd>\n')
# don't add "simple" class value, no special handling of "details"
def visit_definition_list(self, node):
self.body.append(self.starttag(node, 'dl', CLASS='docutils'))
def depart_definition_list(self, node):
self.body.append('</dl>\n')
# no special handling of "details"
def visit_definition_list_item(self, node):
pass
def depart_definition_list_item(self, node):
pass
# use a table for description lists
def visit_description(self, node):
self.body.append(self.starttag(node, 'td', ''))
self.set_first_last(node)
def depart_description(self, node):
self.body.append('</td>')
# use table for docinfo
def visit_docinfo(self, node):
self.context.append(len(self.body))
self.body.append(self.starttag(node, 'table',
CLASS='docinfo',
frame="void", rules="none"))
self.body.append('<col class="docinfo-name" />\n'
'<col class="docinfo-content" />\n'
'<tbody valign="top">\n')
self.in_docinfo = True
def depart_docinfo(self, node):
self.body.append('</tbody>\n</table>\n')
self.in_docinfo = False
start = self.context.pop()
self.docinfo = self.body[start:]
self.body = []
def visit_docinfo_item(self, node, name, meta=True):
if meta:
meta_tag = '<meta name="%s" content="%s" />\n' \
% (name, self.attval(node.astext()))
self.meta.append(meta_tag)
self.body.append(self.starttag(node, 'tr', ''))
self.body.append('<th class="docinfo-name">%s:</th>\n<td>'
% self.language.labels[name])
if len(node):
if isinstance(node[0], nodes.Element):
node[0]['classes'].append('first')
if isinstance(node[-1], nodes.Element):
node[-1]['classes'].append('last')
def depart_docinfo_item(self):
self.body.append('</td></tr>\n')
# add newline after opening tag
def visit_doctest_block(self, node):
self.body.append(self.starttag(node, 'pre', CLASS='doctest-block'))
def depart_doctest_block(self, node):
self.body.append('\n</pre>\n')
# insert an NBSP into empty cells, ersatz for first/last
def visit_entry(self, node):
writers._html_base.HTMLTranslator.visit_entry(self, node)
if len(node) == 0: # empty cell
self.body.append('&nbsp;')
self.set_first_last(node)
def depart_entry(self, node):
self.body.append(self.context.pop())
# ersatz for first/last pseudo-classes
def visit_enumerated_list(self, node):
"""
The 'start' attribute does not conform to HTML 4.01's strict.dtd, but
cannot be emulated in CSS1 (HTML 5 reincludes it).
"""
atts = {}
if 'start' in node:
atts['start'] = node['start']
if 'enumtype' in node:
atts['class'] = node['enumtype']
# @@@ To do: prefix, suffix. How? Change prefix/suffix to a
# single "format" attribute? Use CSS2?
old_compact_simple = self.compact_simple
self.context.append((self.compact_simple, self.compact_p))
self.compact_p = None
self.compact_simple = self.is_compactable(node)
if self.compact_simple and not old_compact_simple:
atts['class'] = (atts.get('class', '') + ' simple').strip()
self.body.append(self.starttag(node, 'ol', **atts))
def depart_enumerated_list(self, node):
self.compact_simple, self.compact_p = self.context.pop()
self.body.append('</ol>\n')
# use table for field-list:
def visit_field(self, node):
self.body.append(self.starttag(node, 'tr', '', CLASS='field'))
def depart_field(self, node):
self.body.append('</tr>\n')
def visit_field_body(self, node):
self.body.append(self.starttag(node, 'td', '', CLASS='field-body'))
self.set_class_on_child(node, 'first', 0)
field = node.parent
if (self.compact_field_list
or isinstance(field.parent, nodes.docinfo)
or field.parent.index(field) == len(field.parent) - 1):
# If we are in a compact list, the docinfo, or if this is
# the last field of the field list, do not add vertical
# space after last element.
self.set_class_on_child(node, 'last', -1)
def depart_field_body(self, node):
self.body.append('</td>\n')
def visit_field_list(self, node):
self.context.append((self.compact_field_list, self.compact_p))
self.compact_p = None
if 'compact' in node['classes']:
self.compact_field_list = True
elif (self.settings.compact_field_lists
and 'open' not in node['classes']):
self.compact_field_list = True
if self.compact_field_list:
for field in node:
field_body = field[-1]
assert isinstance(field_body, nodes.field_body)
children = [n for n in field_body
if not isinstance(n, nodes.Invisible)]
if not (len(children) == 0
or len(children) == 1
and isinstance(children[0],
(nodes.paragraph, nodes.line_block))):
self.compact_field_list = False
break
self.body.append(self.starttag(node, 'table', frame='void',
rules='none',
CLASS='docutils field-list'))
self.body.append('<col class="field-name" />\n'
'<col class="field-body" />\n'
'<tbody valign="top">\n')
def depart_field_list(self, node):
self.body.append('</tbody>\n</table>\n')
self.compact_field_list, self.compact_p = self.context.pop()
def visit_field_name(self, node):
atts = {}
if self.in_docinfo:
atts['class'] = 'docinfo-name'
else:
atts['class'] = 'field-name'
if (self.settings.field_name_limit
and len(node.astext()) > self.settings.field_name_limit):
atts['colspan'] = 2
self.context.append('</tr>\n'
+ self.starttag(node.parent, 'tr', '',
CLASS='field')
+ '<td>&nbsp;</td>')
else:
self.context.append('')
self.body.append(self.starttag(node, 'th', '', **atts))
def depart_field_name(self, node):
self.body.append(':</th>')
self.body.append(self.context.pop())
# use table for footnote text
def visit_footnote(self, node):
self.body.append(self.starttag(node, 'table',
CLASS='docutils footnote',
frame="void", rules="none"))
self.body.append('<colgroup><col class="label" /><col /></colgroup>\n'
'<tbody valign="top">\n'
'<tr>')
self.footnote_backrefs(node)
def footnote_backrefs(self, node):
backlinks = []
backrefs = node['backrefs']
if self.settings.footnote_backlinks and backrefs:
if len(backrefs) == 1:
self.context.append('')
self.context.append('</a>')
self.context.append('<a class="fn-backref" href="#%s">'
% backrefs[0])
else:
for (i, backref) in enumerate(backrefs, 1):
backlinks.append('<a class="fn-backref" href="#%s">%s</a>'
% (backref, i))
self.context.append('<em>(%s)</em> ' % ', '.join(backlinks))
self.context += ['', '']
else:
self.context.append('')
self.context += ['', '']
# If the node does not only consist of a label.
if len(node) > 1:
# If there are preceding backlinks, we do not set class
# 'first', because we need to retain the top-margin.
if not backlinks:
node[1]['classes'].append('first')
node[-1]['classes'].append('last')
def depart_footnote(self, node):
self.body.append('</td></tr>\n'
'</tbody>\n</table>\n')
# insert markers in text (pseudo-classes are not supported in CSS1):
def visit_footnote_reference(self, node):
href = '#' + node['refid']
format = self.settings.footnote_references
if format == 'brackets':
suffix = '['
self.context.append(']')
else:
assert format == 'superscript'
suffix = '<sup>'
self.context.append('</sup>')
self.body.append(self.starttag(node, 'a', suffix,
CLASS='footnote-reference', href=href))
def depart_footnote_reference(self, node):
self.body.append(self.context.pop() + '</a>')
# just pass on generated text
def visit_generated(self, node):
pass
# Backwards-compatibility implementation:
# * Do not use <video>,
# * don't embed images,
# * use <object> instead of <img> for SVG.
# (SVG not supported by IE up to version 8,
# html4css1 strives for IE6 compatibility.)
object_image_types = {'.svg': 'image/svg+xml',
'.swf': 'application/x-shockwave-flash',
'.mp4': 'video/mp4',
'.webm': 'video/webm',
'.ogg': 'video/ogg',
}
def visit_image(self, node):
atts = {}
uri = node['uri']
ext = os.path.splitext(uri)[1].lower()
if ext in self.object_image_types:
atts['data'] = uri
atts['type'] = self.object_image_types[ext]
else:
atts['src'] = uri
atts['alt'] = node.get('alt', uri)
# image size
if 'width' in node:
atts['width'] = node['width']
if 'height' in node:
atts['height'] = node['height']
if 'scale' in node:
if (PIL and ('width' not in node or 'height' not in node)
and self.settings.file_insertion_enabled):
imagepath = self.uri2imagepath(uri)
try:
with PIL.Image.open(imagepath) as img:
img_size = img.size
except (OSError, UnicodeEncodeError):
pass # TODO: warn/info?
else:
self.settings.record_dependencies.add(
imagepath.replace('\\', '/'))
if 'width' not in atts:
atts['width'] = '%dpx' % img_size[0]
if 'height' not in atts:
atts['height'] = '%dpx' % img_size[1]
for att_name in 'width', 'height':
if att_name in atts:
match = re.match(r'([0-9.]+)(\S*)$', atts[att_name])
assert match
atts[att_name] = '%s%s' % (
float(match.group(1)) * (float(node['scale']) / 100),
match.group(2))
style = []
for att_name in 'width', 'height':
if att_name in atts:
if re.match(r'^[0-9.]+$', atts[att_name]):
# Interpret unitless values as pixels.
atts[att_name] += 'px'
style.append('%s: %s;' % (att_name, atts[att_name]))
del atts[att_name]
if style:
atts['style'] = ' '.join(style)
# No newlines around inline images.
if (not isinstance(node.parent, nodes.TextElement)
or isinstance(node.parent, nodes.reference)
and not isinstance(node.parent.parent, nodes.TextElement)):
suffix = '\n'
else:
suffix = ''
if 'align' in node:
atts['class'] = 'align-%s' % node['align']
if ext in self.object_image_types:
# do NOT use an empty tag: incorrect rendering in browsers
self.body.append(self.starttag(node, 'object', '', **atts)
+ node.get('alt', uri) + '</object>' + suffix)
else:
self.body.append(self.emptytag(node, 'img', suffix, **atts))
def depart_image(self, node):
pass
# use table for footnote text,
# context added in footnote_backrefs.
def visit_label(self, node):
self.body.append(self.starttag(node, 'td', '%s[' % self.context.pop(),
CLASS='label'))
def depart_label(self, node):
self.body.append(f']{self.context.pop()}</td><td>{self.context.pop()}')
# ersatz for first/last pseudo-classes
def visit_list_item(self, node):
self.body.append(self.starttag(node, 'li', ''))
if len(node):
node[0]['classes'].append('first')
def depart_list_item(self, node):
self.body.append('</li>\n')
# use <tt> (not supported by HTML5),
# cater for limited styling options in CSS1 using hard-coded NBSPs
def visit_literal(self, node):
# special case: "code" role
classes = node['classes']
if 'code' in classes:
# filter 'code' from class arguments
node['classes'] = [cls for cls in classes if cls != 'code']
self.body.append(self.starttag(node, 'code', ''))
return
self.body.append(
self.starttag(node, 'tt', '', CLASS='docutils literal'))
text = node.astext()
for token in self.words_and_spaces.findall(text):
if token.strip():
# Protect text like "--an-option" and the regular expression
# ``[+]?(\d+(\.\d*)?|\.\d+)`` from bad line wrapping
if self.in_word_wrap_point.search(token):
self.body.append('<span class="pre">%s</span>'
% self.encode(token))
else:
self.body.append(self.encode(token))
elif token in ('\n', ' '):
# Allow breaks at whitespace:
self.body.append(token)
else:
# Protect runs of multiple spaces; the last space can wrap:
self.body.append('&nbsp;' * (len(token) - 1) + ' ')
self.body.append('</tt>')
# Content already processed:
raise nodes.SkipNode
def depart_literal(self, node):
# skipped unless literal element is from "code" role:
self.body.append('</code>')
# add newline after wrapper tags, don't use <code> for code
def visit_literal_block(self, node):
self.body.append(self.starttag(node, 'pre', CLASS='literal-block'))
def depart_literal_block(self, node):
self.body.append('\n</pre>\n')
# use table for option list
def visit_option_group(self, node):
atts = {}
if (self.settings.option_limit
and len(node.astext()) > self.settings.option_limit):
atts['colspan'] = 2
self.context.append('</tr>\n<tr><td>&nbsp;</td>')
else:
self.context.append('')
self.body.append(
self.starttag(node, 'td', CLASS='option-group', **atts))
self.body.append('<kbd>')
self.context.append(0) # count number of options
def depart_option_group(self, node):
self.context.pop()
self.body.append('</kbd></td>\n')
self.body.append(self.context.pop())
def visit_option_list(self, node):
self.body.append(
self.starttag(node, 'table', CLASS='docutils option-list',
frame="void", rules="none"))
self.body.append('<col class="option" />\n'
'<col class="description" />\n'
'<tbody valign="top">\n')
def depart_option_list(self, node):
self.body.append('</tbody>\n</table>\n')
def visit_option_list_item(self, node):
self.body.append(self.starttag(node, 'tr', ''))
def depart_option_list_item(self, node):
self.body.append('</tr>\n')
# Omit <p> tags to produce visually compact lists (less vertical
# whitespace) as CSS styling requires CSS2.
def should_be_compact_paragraph(self, node):
"""
Determine if the <p> tags around paragraph ``node`` can be omitted.
"""
if (isinstance(node.parent, nodes.document)
or isinstance(node.parent, nodes.compound)):
# Never compact paragraphs in document or compound.
return False
for key, value in node.attlist():
if (node.is_not_default(key)
and not (key == 'classes'
and value in ([], ['first'],
['last'], ['first', 'last']))):
# Attribute which needs to survive.
return False
first = isinstance(node.parent[0], nodes.label) # skip label
for child in node.parent.children[first:]:
# only first paragraph can be compact
if isinstance(child, nodes.Invisible):
continue
if child is node:
break
return False
parent_length = len([n for n in node.parent if not isinstance(
n, (nodes.Invisible, nodes.label))])
if (self.compact_simple
or self.compact_field_list
or self.compact_p and parent_length == 1):
return True
return False
def visit_paragraph(self, node):
if self.should_be_compact_paragraph(node):
self.context.append('')
else:
self.body.append(self.starttag(node, 'p', ''))
self.context.append('</p>\n')
def depart_paragraph(self, node):
self.body.append(self.context.pop())
self.report_messages(node)
# ersatz for first/last pseudo-classes
def visit_sidebar(self, node):
self.body.append(
self.starttag(node, 'div', CLASS='sidebar'))
self.set_first_last(node)
self.in_sidebar = True
def depart_sidebar(self, node):
self.body.append('</div>\n')
self.in_sidebar = False
# <sub> not allowed in <pre>
def visit_subscript(self, node):
if isinstance(node.parent, nodes.literal_block):
self.body.append(self.starttag(node, 'span', '',
CLASS='subscript'))
else:
self.body.append(self.starttag(node, 'sub', ''))
def depart_subscript(self, node):
if isinstance(node.parent, nodes.literal_block):
self.body.append('</span>')
else:
self.body.append('</sub>')
# Use <h*> for subtitles (deprecated in HTML 5)
def visit_subtitle(self, node):
if isinstance(node.parent, nodes.sidebar):
self.body.append(self.starttag(node, 'p', '',
CLASS='sidebar-subtitle'))
self.context.append('</p>\n')
elif isinstance(node.parent, nodes.document):
self.body.append(self.starttag(node, 'h2', '', CLASS='subtitle'))
self.context.append('</h2>\n')
self.in_document_title = len(self.body)
elif isinstance(node.parent, nodes.section):
tag = 'h%s' % (self.section_level + self.initial_header_level - 1)
self.body.append(
self.starttag(node, tag, '', CLASS='section-subtitle')
+ self.starttag({}, 'span', '', CLASS='section-subtitle'))
self.context.append('</span></%s>\n' % tag)
def depart_subtitle(self, node):
self.body.append(self.context.pop())
if self.in_document_title:
self.subtitle = self.body[self.in_document_title:-1]
self.in_document_title = 0
self.body_pre_docinfo.extend(self.body)
self.html_subtitle.extend(self.body)
del self.body[:]
# <sup> not allowed in <pre> in HTML 4
def visit_superscript(self, node):
if isinstance(node.parent, nodes.literal_block):
self.body.append(self.starttag(node, 'span', '',
CLASS='superscript'))
else:
self.body.append(self.starttag(node, 'sup', ''))
def depart_superscript(self, node):
if isinstance(node.parent, nodes.literal_block):
self.body.append('</span>')
else:
self.body.append('</sup>')
# <tt> element deprecated in HTML 5
def visit_system_message(self, node):
self.body.append(self.starttag(node, 'div', CLASS='system-message'))
self.body.append('<p class="system-message-title">')
backref_text = ''
if len(node['backrefs']):
backrefs = node['backrefs']
if len(backrefs) == 1:
backref_text = ('; <em><a href="#%s">backlink</a></em>'
% backrefs[0])
else:
i = 1
backlinks = []
for backref in backrefs:
backlinks.append('<a href="#%s">%s</a>' % (backref, i))
i += 1
backref_text = ('; <em>backlinks: %s</em>'
% ', '.join(backlinks))
if node.hasattr('line'):
line = ', line %s' % node['line']
else:
line = ''
self.body.append('System Message: %s/%s '
'(<tt class="docutils">%s</tt>%s)%s</p>\n'
% (node['type'], node['level'],
self.encode(node['source']), line, backref_text))
def depart_system_message(self, node):
self.body.append('</div>\n')
# "hard coded" border setting
def visit_table(self, node):
self.context.append(self.compact_p)
self.compact_p = True
atts = {'border': 1}
classes = ['docutils', self.settings.table_style]
if 'align' in node:
classes.append('align-%s' % node['align'])
if 'width' in node:
atts['style'] = 'width: %s' % node['width']
self.body.append(
self.starttag(node, 'table', CLASS=' '.join(classes), **atts))
def depart_table(self, node):
self.compact_p = self.context.pop()
self.body.append('</table>\n')
# hard-coded vertical alignment
def visit_tbody(self, node):
self.body.append(self.starttag(node, 'tbody', valign='top'))
def depart_tbody(self, node):
self.body.append('</tbody>\n')
# no special handling of "details" in definition list
def visit_term(self, node):
self.body.append(self.starttag(node, 'dt', '',
classes=node.parent['classes'],
ids=node.parent['ids']))
def depart_term(self, node):
# Nest (optional) classifier(s) in the <dt> element
if node.next_node(nodes.classifier, descend=False, siblings=True):
return # skip (depart_classifier() calls this function again)
self.body.append('</dt>\n')
# hard-coded vertical alignment
def visit_thead(self, node):
self.body.append(self.starttag(node, 'thead', valign='bottom'))
def depart_thead(self, node):
self.body.append('</thead>\n')
# auxiliary method, called by visit_title()
# "with-subtitle" class, no ARIA roles
def section_title_tags(self, node):
classes = []
h_level = self.section_level + self.initial_header_level - 1
if (len(node.parent) >= 2
and isinstance(node.parent[1], nodes.subtitle)):
classes.append('with-subtitle')
if h_level > 6:
classes.append('h%i' % h_level)
tagname = 'h%i' % min(h_level, 6)
start_tag = self.starttag(node, tagname, '', classes=classes)
if node.hasattr('refid'):
atts = {}
atts['class'] = 'toc-backref'
atts['href'] = '#' + node['refid']
start_tag += self.starttag({}, 'a', '', **atts)
close_tag = '</a></%s>\n' % tagname
else:
close_tag = '</%s>\n' % tagname
return start_tag, close_tag
class SimpleListChecker(writers._html_base.SimpleListChecker):
"""
Raise `nodes.NodeFound` if non-simple list item is encountered.
Here "simple" means a list item containing nothing other than a single
paragraph, a simple list, or a paragraph followed by a simple list.
"""
def visit_list_item(self, node):
children = []
for child in node.children:
if not isinstance(child, nodes.Invisible):
children.append(child)
if (children and isinstance(children[0], nodes.paragraph)
and (isinstance(children[-1], nodes.bullet_list)
or isinstance(children[-1], nodes.enumerated_list))):
children.pop()
if len(children) <= 1:
return
else:
raise nodes.NodeFound
# def visit_bullet_list(self, node):
# pass
# def visit_enumerated_list(self, node):
# pass
def visit_paragraph(self, node):
raise nodes.SkipNode
def visit_definition_list(self, node):
raise nodes.NodeFound
def visit_docinfo(self, node):
raise nodes.NodeFound

View file

@ -0,0 +1,350 @@
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }

View file

@ -0,0 +1,8 @@
%(head_prefix)s
%(head)s
%(stylesheet)s
%(body_prefix)s
%(body_pre_docinfo)s
%(docinfo)s
%(body)s
%(body_suffix)s

View file

@ -0,0 +1,393 @@
# $Id: __init__.py 9539 2024-02-17 10:36:51Z milde $
# :Author: Günter Milde <milde@users.sf.net>
# Based on the html4css1 writer by David Goodger.
# :Maintainer: docutils-develop@lists.sourceforge.net
# :Copyright: © 2005, 2009, 2015 Günter Milde,
# portions from html4css1 © David Goodger.
# :License: Released under the terms of the `2-Clause BSD license`_, in short:
#
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.
# This file is offered as-is, without any warranty.
#
# .. _2-Clause BSD license: https://opensource.org/licenses/BSD-2-Clause
# Use "best practice" as recommended by the W3C:
# http://www.w3.org/2009/cheatsheet/
"""
Plain HyperText Markup Language document tree Writer.
The output conforms to the `HTML 5` specification.
The cascading style sheet "minimal.css" is required for proper viewing,
the style sheet "plain.css" improves reading experience.
"""
__docformat__ = 'reStructuredText'
from pathlib import Path
from docutils import frontend, nodes
from docutils.writers import _html_base
class Writer(_html_base.Writer):
supported = ('html5', 'xhtml', 'html')
"""Formats this writer supports."""
default_stylesheets = ['minimal.css', 'plain.css']
default_stylesheet_dirs = ['.', str(Path(__file__).parent)]
default_template = Path(__file__).parent / 'template.txt'
# use a copy of the parent spec with some modifications
settings_spec = frontend.filter_settings_spec(
_html_base.Writer.settings_spec,
template=(
f'Template file. (UTF-8 encoded, default: "{default_template}")',
['--template'],
{'default': default_template, 'metavar': '<file>'}),
stylesheet_path=(
'Comma separated list of stylesheet paths. '
'Relative paths are expanded if a matching file is found in '
'the --stylesheet-dirs. With --link-stylesheet, '
'the path is rewritten relative to the output HTML file. '
'(default: "%s")' % ','.join(default_stylesheets),
['--stylesheet-path'],
{'metavar': '<file[,file,...]>', 'overrides': 'stylesheet',
'validator': frontend.validate_comma_separated_list,
'default': default_stylesheets}),
stylesheet_dirs=(
'Comma-separated list of directories where stylesheets are found. '
'Used by --stylesheet-path when expanding relative path '
'arguments. (default: "%s")' % ','.join(default_stylesheet_dirs),
['--stylesheet-dirs'],
{'metavar': '<dir[,dir,...]>',
'validator': frontend.validate_comma_separated_list,
'default': default_stylesheet_dirs}),
initial_header_level=(
'Specify the initial header level. Does not affect document '
'title & subtitle (see --no-doc-title). (default: 2 for "<h2>")',
['--initial-header-level'],
{'choices': '1 2 3 4 5 6'.split(), 'default': '2',
'metavar': '<level>'}),
no_xml_declaration=(
'Omit the XML declaration (default).',
['--no-xml-declaration'],
{'dest': 'xml_declaration', 'action': 'store_false'}),
)
settings_spec = settings_spec + (
'HTML5 Writer Options',
'',
((frontend.SUPPRESS_HELP, # Obsoleted by "--image-loading"
['--embed-images'],
{'action': 'store_true',
'validator': frontend.validate_boolean}),
(frontend.SUPPRESS_HELP, # Obsoleted by "--image-loading"
['--link-images'],
{'dest': 'embed_images', 'action': 'store_false'}),
('Suggest at which point images should be loaded: '
'"embed", "link" (default), or "lazy".',
['--image-loading'],
{'choices': ('embed', 'link', 'lazy'),
# 'default': 'link' # default set in _html_base.py
}),
('Append a self-link to section headings.',
['--section-self-link'],
{'default': False, 'action': 'store_true'}),
('Do not append a self-link to section headings. (default)',
['--no-section-self-link'],
{'dest': 'section_self_link', 'action': 'store_false'}),
)
)
config_section = 'html5 writer'
def __init__(self):
self.parts = {}
self.translator_class = HTMLTranslator
class HTMLTranslator(_html_base.HTMLTranslator):
"""
This writer generates `polyglot markup`: HTML5 that is also valid XML.
Safe subclassing: when overriding, treat ``visit_*`` and ``depart_*``
methods as a unit to prevent breaks due to internal changes. See the
docstring of docutils.writers._html_base.HTMLTranslator for details
and examples.
"""
# self.starttag() arguments for the main document
documenttag_args = {'tagname': 'main'}
# add meta tag to fix rendering in mobile browsers
def __init__(self, document):
super().__init__(document)
self.meta.append('<meta name="viewport" '
'content="width=device-width, initial-scale=1" />\n')
# <acronym> tag obsolete in HTML5. Use the <abbr> tag instead.
def visit_acronym(self, node):
# @@@ implementation incomplete ("title" attribute)
self.body.append(self.starttag(node, 'abbr', ''))
def depart_acronym(self, node):
self.body.append('</abbr>')
# no standard meta tag name in HTML5, use separate "author" meta tags
# https://www.w3.org/TR/html5/document-metadata.html#standard-metadata-names
def visit_authors(self, node):
self.visit_docinfo_item(node, 'authors', meta=False)
for subnode in node:
self.meta.append('<meta name="author" content='
f'"{self.attval(subnode.astext())}" />\n')
def depart_authors(self, node):
self.depart_docinfo_item()
# use the <figcaption> semantic tag.
def visit_caption(self, node):
if isinstance(node.parent, nodes.figure):
self.body.append('<figcaption>\n')
self.body.append(self.starttag(node, 'p', ''))
def depart_caption(self, node):
self.body.append('</p>\n')
# <figcaption> is closed in depart_figure(), as legend may follow.
# use HTML block-level tags if matching class value found
supported_block_tags = {'ins', 'del'}
def visit_container(self, node):
# If there is exactly one of the "supported block tags" in
# the list of class values, use it as tag name:
classes = node['classes']
tags = [cls for cls in classes
if cls in self.supported_block_tags]
if len(tags) == 1:
node.html5tagname = tags[0]
classes.remove(tags[0])
else:
node.html5tagname = 'div'
self.body.append(self.starttag(node, node.html5tagname,
CLASS='docutils container'))
def depart_container(self, node):
self.body.append(f'</{node.html5tagname}>\n')
del node.html5tagname
# no standard meta tag name in HTML5, use dcterms.rights
# see https://wiki.whatwg.org/wiki/MetaExtensions
def visit_copyright(self, node):
self.visit_docinfo_item(node, 'copyright', meta=False)
self.meta.append('<meta name="dcterms.rights" '
f'content="{self.attval(node.astext())}" />\n')
def depart_copyright(self, node):
self.depart_docinfo_item()
# no standard meta tag name in HTML5, use dcterms.date
def visit_date(self, node):
self.visit_docinfo_item(node, 'date', meta=False)
self.meta.append('<meta name="dcterms.date" '
f'content="{self.attval(node.astext())}" />\n')
def depart_date(self, node):
self.depart_docinfo_item()
# use new HTML5 <figure> and <figcaption> elements
def visit_figure(self, node):
atts = {}
if node.get('width'):
atts['style'] = f"width: {node['width']}"
if node.get('align'):
atts['class'] = f"align-{node['align']}"
self.body.append(self.starttag(node, 'figure', **atts))
def depart_figure(self, node):
if len(node) > 1:
self.body.append('</figcaption>\n')
self.body.append('</figure>\n')
# use HTML5 <footer> element
def visit_footer(self, node):
self.context.append(len(self.body))
def depart_footer(self, node):
start = self.context.pop()
footer = [self.starttag(node, 'footer')]
footer.extend(self.body[start:])
footer.append('</footer>\n')
self.footer.extend(footer)
self.body_suffix[:0] = footer
del self.body[start:]
# use HTML5 <header> element
def visit_header(self, node):
self.context.append(len(self.body))
def depart_header(self, node):
start = self.context.pop()
header = [self.starttag(node, 'header')]
header.extend(self.body[start:])
header.append('</header>\n')
self.body_prefix.extend(header)
self.header.extend(header)
del self.body[start:]
# use HTML text-level tags if matching class value found
supported_inline_tags = {'code', 'kbd', 'dfn', 'samp', 'var',
'bdi', 'del', 'ins', 'mark', 'small',
'b', 'i', 'q', 's', 'u'}
# Use `supported_inline_tags` if found in class values
def visit_inline(self, node):
classes = node['classes']
node.html5tagname = 'span'
# Special handling for "code" directive content
if (isinstance(node.parent, nodes.literal_block)
and 'code' in node.parent.get('classes')
or isinstance(node.parent, nodes.literal)
and getattr(node.parent, 'html5tagname', None) == 'code'):
if classes == ['ln']:
# line numbers are not part of the "fragment of computer code"
if self.body[-1] == '<code>':
del self.body[-1]
else:
self.body.append('</code>')
node.html5tagname = 'small'
else:
tags = [cls for cls in self.supported_inline_tags
if cls in classes]
if len(tags):
node.html5tagname = tags[0]
classes.remove(node.html5tagname)
self.body.append(self.starttag(node, node.html5tagname, ''))
def depart_inline(self, node):
self.body.append(f'</{node.html5tagname}>')
if (node.html5tagname == 'small' and node.get('classes') == ['ln']
and isinstance(node.parent, nodes.literal_block)):
self.body.append(f'<code data-lineno="{node.astext()}">')
del node.html5tagname
# place inside HTML5 <figcaption> element (together with caption)
def visit_legend(self, node):
if not isinstance(node.parent[1], nodes.caption):
self.body.append('<figcaption>\n')
self.body.append(self.starttag(node, 'div', CLASS='legend'))
def depart_legend(self, node):
self.body.append('</div>\n')
# <figcaption> closed in visit_figure()
# use HTML5 text-level tags if matching class value found
def visit_literal(self, node):
classes = node['classes']
html5tagname = 'span'
tags = [cls for cls in self.supported_inline_tags
if cls in classes]
if len(tags):
html5tagname = tags[0]
classes.remove(html5tagname)
if html5tagname == 'code':
node.html5tagname = html5tagname
self.body.append(self.starttag(node, html5tagname, ''))
return
self.body.append(
self.starttag(node, html5tagname, '', CLASS='docutils literal'))
text = node.astext()
# remove hard line breaks (except if in a parsed-literal block)
if not isinstance(node.parent, nodes.literal_block):
text = text.replace('\n', ' ')
# Protect text like ``--an-option`` and the regular expression
# ``[+]?(\d+(\.\d*)?|\.\d+)`` from bad line wrapping
for token in self.words_and_spaces.findall(text):
if token.strip() and self.in_word_wrap_point.search(token):
self.body.append(
f'<span class="pre">{self.encode(token)}</span>')
else:
self.body.append(self.encode(token))
self.body.append(f'</{html5tagname}>')
# Content already processed:
raise nodes.SkipNode
def depart_literal(self, node):
# skipped unless literal element is from "code" role:
self.depart_inline(node)
# Meta tags: 'lang' attribute replaced by 'xml:lang' in XHTML 1.1
# HTML5/polyglot recommends using both
def visit_meta(self, node):
if node.hasattr('lang'):
node['xml:lang'] = node['lang']
self.meta.append(self.emptytag(node, 'meta',
**node.non_default_attributes()))
def depart_meta(self, node):
pass
# no standard meta tag name in HTML5
def visit_organization(self, node):
self.visit_docinfo_item(node, 'organization', meta=False)
def depart_organization(self, node):
self.depart_docinfo_item()
# use the new HTML5 element <section>
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>\n')
# use the new HTML5 element <aside>
def visit_sidebar(self, node):
self.body.append(
self.starttag(node, 'aside', CLASS='sidebar'))
self.in_sidebar = True
def depart_sidebar(self, node):
self.body.append('</aside>\n')
self.in_sidebar = False
# Use new HTML5 element <aside> or <nav>
# Add class value to <body>, if there is a ToC in the document
# (see responsive.css how this is used for a navigation sidebar).
def visit_topic(self, node):
atts = {'classes': ['topic']}
if 'contents' in node['classes']:
node.html5tagname = 'nav'
del atts['classes']
if isinstance(node.parent, nodes.document):
atts['role'] = 'doc-toc'
self.body_prefix[0] = '</head>\n<body class="with-toc">\n'
elif 'abstract' in node['classes']:
node.html5tagname = 'div'
atts['role'] = 'doc-abstract'
elif 'dedication' in node['classes']:
node.html5tagname = 'div'
atts['role'] = 'doc-dedication'
else:
node.html5tagname = 'aside'
self.body.append(self.starttag(node, node.html5tagname, **atts))
def depart_topic(self, node):
self.body.append(f'</{node.html5tagname}>\n')
del node.html5tagname
# append self-link
def section_title_tags(self, node):
start_tag, close_tag = super().section_title_tags(node)
ids = node.parent['ids']
if (ids and getattr(self.settings, 'section_self_link', None)
and not isinstance(node.parent, nodes.document)):
self_link = ('<a class="self-link" title="link to this section"'
f' href="#{ids[0]}"></a>')
close_tag = close_tag.replace('</h', self_link + '</h')
return start_tag, close_tag

View file

@ -0,0 +1,26 @@
/* italic-field-name.css: */
/* Alternative style for Docutils field-lists */
/* :Copyright: © 2023 Günter Milde. */
/* :License: Released under the terms of the `2-Clause BSD license`_, */
/* in short: */
/* */
/* Copying and distribution of this file, with or without modification, */
/* are permitted in any medium without royalty provided the copyright */
/* notice and this notice are preserved. */
/* */
/* This file is offered as-is, without any warranty. */
/* */
/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
/* In many contexts, a **bold** field name is too heavy styling. */
/* Use *italic* instead:: */
dl.field-list > dt {
font-weight: normal;
font-style: italic;
}
dl.field-list > dt > .colon {
font-style: normal;
padding-left: 0.05ex;
}

View file

@ -0,0 +1,332 @@
/*
* math2html: convert LaTeX equations to HTML output.
*
* Copyright (C) 2009,2010 Alex Fernández
* 2021 Günter Milde
*
* Released under the terms of the `2-Clause BSD license'_, in short:
* Copying and distribution of this file, with or without modification,
* are permitted in any medium without royalty provided the copyright
* notice and this notice are preserved.
* This file is offered as-is, without any warranty.
*
* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
*
* Based on eLyXer: convert LyX source files to HTML output.
* http://elyxer.nongnu.org/
*
*
* CSS file for LaTeX formulas.
*
* References: http://www.zipcon.net/~swhite/docs/math/math.html
* http://www.cs.tut.fi/~jkorpela/math/
*/
/* Formulas */
.formula {
text-align: center;
margin: 1.2em 0;
line-height: 1.4;
}
span.formula {
white-space: nowrap;
}
div.formula {
padding: 0.5ex;
margin-left: auto;
margin-right: auto;
}
/* Basic features */
a.eqnumber {
display: inline-block;
float: right;
clear: right;
font-weight: bold;
}
span.unknown {
color: #800000;
}
span.ignored, span.arraydef {
display: none;
}
.phantom {
visibility: hidden;
}
.formula i {
letter-spacing: 0.1ex;
}
/* Alignment */
.align-l {
text-align: left;
}
.align-r {
text-align: right;
}
.align-c {
text-align: center;
}
/* Structures */
span.hspace {
display: inline-block;
}
span.overline, span.bar {
text-decoration: overline;
}
.fraction, .fullfraction, .textfraction {
display: inline-block;
vertical-align: middle;
text-align: center;
}
span.formula .fraction,
.textfraction,
span.smallmatrix {
font-size: 80%;
line-height: 1;
}
span.numerator {
display: block;
line-height: 1;
}
span.denominator {
display: block;
line-height: 1;
padding: 0ex;
border-top: thin solid;
}
.formula sub, .formula sup {
font-size: 80%;
}
sup.numerator, sup.unit {
vertical-align: 80%;
}
sub.denominator, sub.unit {
vertical-align: -20%;
}
span.smallsymbol {
font-size: 75%;
line-height: 75%;
}
span.boldsymbol {
font-weight: bold;
}
span.sqrt {
display: inline-block;
vertical-align: middle;
padding: 0.1ex;
}
sup.root {
position: relative;
left: 1.4ex;
}
span.radical {
display: inline-block;
padding: 0ex;
/* font-size: 160%; for DejaVu, not required with STIX */
line-height: 100%;
vertical-align: top;
vertical-align: middle;
}
span.root {
display: inline-block;
border-top: thin solid;
padding: 0ex;
vertical-align: middle;
}
div.formula .bigoperator,
.displaystyle .bigoperator,
.displaystyle .bigoperator {
line-height: 120%;
font-size: 140%;
padding-right: 0.2ex;
}
span.fraction .bigoperator,
span.scriptstyle .bigoperator {
line-height: inherit;
font-size: inherit;
padding-right: 0;
}
span.bigdelimiter {
display: inline-block;
}
span.bigdelimiter.size1 {
transform: scale(1, 1.2);
line-height: 1.2;
}
span.bigdelimiter.size2 {
transform: scale(1, 1.62);
line-height: 1.62%;
}
span.bigdelimiter.size3 {
transform: scale(1, 2.05);
line-height: 2.05%;
}
span.bigdelimiter.size4 {
transform: scale(1, 2.47);
line-height: 2.47%;
}
/* vertically stacked sub and superscript */
span.scripts {
display: inline-table;
vertical-align: middle;
padding-right: 0.2ex;
}
.script {
display: table-row;
text-align: left;
line-height: 150%;
}
span.limits {
display: inline-table;
vertical-align: middle;
}
.limit {
display: table-row;
line-height: 99%;
}
sup.limit, sub.limit {
line-height: 100%;
}
span.embellished,
span.embellished > .base {
display: inline-block;
}
span.embellished > sup,
span.embellished > sub {
display: inline-block;
font-size: 100%;
position: relative;
bottom: 0.3em;
width: 0px;
}
span.embellished > sub {
top: 0.4em;
}
/* Environments */
span.array, span.bracketcases, span.binomial, span.environment {
display: inline-table;
text-align: center;
vertical-align: middle;
}
span.arrayrow, span.binomrow {
display: table-row;
padding: 0;
border: 0;
}
span.arraycell, span.bracket, span.case, span.binomcell, span.environmentcell {
display: table-cell;
padding: 0ex 0.2ex;
line-height: 1; /* 99%; */
border: 0ex;
}
.environment.align > .arrayrow > .arraycell.align-l {
padding-right: 2em;
}
/* Inline binomials */
span.binom {
display: inline-block;
vertical-align: middle;
text-align: center;
font-size: 80%;
}
span.binomstack {
display: block;
padding: 0em;
}
/* Over- and underbraces */
span.overbrace {
border-top: 2pt solid;
}
span.underbrace {
border-bottom: 2pt solid;
}
/* Stackrel */
span.stackrel {
display: inline-block;
text-align: center;
}
span.upstackrel {
display: block;
padding: 0em;
font-size: 80%;
line-height: 64%;
position: relative;
top: 0.15em;
}
span.downstackrel {
display: block;
vertical-align: bottom;
padding: 0em;
}
/* Fonts */
.formula {
font-family: STIX, "DejaVu Serif", "DejaVu Math TeX Gyre", serif;
}
span.radical, /* ensure correct size of square-root sign */
span.integral { /* upright integral signs for better alignment of indices */
font-family: "STIXIntegralsUp", STIX;
/* font-size: 115%; match apparent size with DejaVu */
}
span.bracket {
/* some "STIX" and "DejaVu Math TeX Gyre" bracket pieces don't fit */
font-family: "DejaVu Serif", serif;
}
span.mathsf, span.textsf {
font-family: sans-serif;
}
span.mathrm, span.textrm {
font-family: STIX, "DejaVu Serif", "DejaVu Math TeX Gyre", serif;
}
span.mathtt, span.texttt {
font-family: monospace;
}
span.text, span.textnormal,
span.mathsf, span.mathtt, span.mathrm {
font-style: normal;
}
span.fraktur {
font-family: "Lucida Blackletter", eufm10, blackletter;
}
span.blackboard {
font-family: Blackboard, msbm10, serif;
}
span.scriptfont {
font-family: "Monotype Corsiva", "Apple Chancery", "URW Chancery L", cursive;
font-style: italic;
}
span.mathscr {
font-family: MathJax_Script, rsfs10, cursive;
font-style: italic;
}
span.textsc {
font-variant: small-caps;
}
span.textsl {
font-style: oblique;
}
/* Colors */
span.colorbox {
display: inline-block;
padding: 5px;
}
span.fbox {
display: inline-block;
border: thin solid black;
padding: 2px;
}
span.boxed, span.framebox {
display: inline-block;
border: thin solid black;
padding: 5px;
}

View file

@ -0,0 +1,293 @@
/* Minimal style sheet for the HTML output of Docutils. */
/* */
/* :Author: Günter Milde, based on html4css1.css by David Goodger */
/* :Id: $Id: minimal.css 9545 2024-02-17 10:37:56Z milde $ */
/* :Copyright: © 2015, 2021 Günter Milde. */
/* :License: Released under the terms of the `2-Clause BSD license`_, */
/* in short: */
/* */
/* Copying and distribution of this file, with or without modification, */
/* are permitted in any medium without royalty provided the copyright */
/* notice and this notice are preserved. */
/* */
/* This file is offered as-is, without any warranty. */
/* */
/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
/* This CSS3 stylesheet defines rules for Docutils elements without */
/* HTML equivalent. It is required to make the document semantics visible. */
/* */
/* .. _validates: http://jigsaw.w3.org/css-validator/validator$link */
/* titles */
p.topic-title,
p.admonition-title,
p.system-message-title {
font-weight: bold;
}
p.sidebar-title,
p.rubric {
font-weight: bold;
font-size: larger;
}
p.rubric {
color: maroon;
}
p.subtitle,
p.section-subtitle,
p.sidebar-subtitle {
font-weight: bold;
margin-top: -0.5em;
}
h1 + p.subtitle {
font-size: 1.6em;
}
a.toc-backref {
color: inherit;
text-decoration: none;
}
/* Warnings, Errors */
.system-messages h2,
.system-message-title,
pre.problematic,
span.problematic {
color: red;
}
/* Inline Literals */
.docutils.literal {
font-family: monospace;
white-space: pre-wrap;
}
/* do not wrap at hyphens and similar: */
.literal > span.pre { white-space: nowrap; }
/* keep line-breaks (\n) visible */
.pre-wrap { white-space: pre-wrap; }
/* Lists */
/* compact and simple lists: no margin between items */
.simple li, .simple ul, .simple ol,
.compact li, .compact ul, .compact ol,
.simple > li p, dl.simple > dd,
.compact > li p, dl.compact > dd {
margin-top: 0;
margin-bottom: 0;
}
/* Nested Paragraphs */
p:first-child { margin-top: 0; }
p:last-child { margin-bottom: 0; }
details > p:last-child { margin-bottom: 1em; }
/* Table of Contents */
.contents ul.auto-toc { /* section numbers present */
list-style-type: none;
}
/* Enumerated Lists */
ol.arabic { list-style: decimal }
ol.loweralpha { list-style: lower-alpha }
ol.upperalpha { list-style: upper-alpha }
ol.lowerroman { list-style: lower-roman }
ol.upperroman { list-style: upper-roman }
/* Definition Lists and Derivatives */
dt .classifier { font-style: italic }
dt .classifier:before {
font-style: normal;
margin: 0.5em;
content: ":";
}
/* Field Lists and similar */
/* bold field name, content starts on the same line */
dl.field-list,
dl.option-list,
dl.docinfo {
display: flow-root;
}
dl.field-list > dt,
dl.option-list > dt,
dl.docinfo > dt {
font-weight: bold;
clear: left;
float: left;
margin: 0;
padding: 0;
padding-right: 0.25em;
}
/* Offset for field content (corresponds to the --field-name-limit option) */
dl.field-list > dd,
dl.option-list > dd,
dl.docinfo > dd {
margin-left: 9em; /* ca. 14 chars in the test examples, fit all Docinfo fields */
}
/* start nested lists on new line */
dd > dl:first-child,
dd > ul:first-child,
dd > ol:first-child {
clear: left;
}
/* start field-body on a new line after long field names */
dl.field-list > dd > *:first-child,
dl.option-list > dd > *:first-child
{
display: inline-block;
width: 100%;
margin: 0;
}
/* Bibliographic Fields (docinfo) */
dl.docinfo pre.address {
font: inherit;
margin: 0.5em 0;
}
dl.docinfo > dd.authors > p { margin: 0; }
/* Option Lists */
dl.option-list > dt { font-weight: normal; }
span.option { white-space: nowrap; }
/* Footnotes and Citations */
.footnote, .citation { margin: 1em 0; } /* default paragraph skip (Firefox) */
/* hanging indent */
.citation { padding-left: 2em; }
.footnote { padding-left: 1.7em; }
.footnote.superscript { padding-left: 1.0em; }
.citation > .label { margin-left: -2em; }
.footnote > .label { margin-left: -1.7em; }
.footnote.superscript > .label { margin-left: -1.0em; }
.footnote > .label + *,
.citation > .label + * {
display: inline-block;
margin-top: 0;
vertical-align: top;
}
.footnote > .backrefs + *,
.citation > .backrefs + * {
margin-top: 0;
}
.footnote > .label + p, .footnote > .backrefs + p,
.citation > .label + p, .citation > .backrefs + p {
display: inline;
vertical-align: inherit;
}
.backrefs { user-select: none; }
.backrefs > a { font-style: italic; }
/* superscript footnotes */
a[role="doc-noteref"].superscript,
.footnote.superscript > .label,
.footnote.superscript > .backrefs {
vertical-align: super;
font-size: smaller;
line-height: 1;
}
a[role="doc-noteref"].superscript > .fn-bracket,
.footnote.superscript > .label > .fn-bracket {
/* hide brackets in display but leave for copy/paste */
display: inline-block;
width: 0;
overflow: hidden;
}
[role="doc-noteref"].superscript + [role="doc-noteref"].superscript {
padding-left: 0.15em; /* separate consecutive footnote references */
/* TODO: unfortunately, "+" also selects with text between the references. */
}
/* Alignment */
.align-left {
text-align: left;
margin-right: auto;
}
.align-center {
text-align: center;
margin-left: auto;
margin-right: auto;
}
.align-right {
text-align: right;
margin-left: auto;
}
.align-top { vertical-align: top; }
.align-middle { vertical-align: middle; }
.align-bottom { vertical-align: bottom; }
/* reset inner alignment in figures and tables */
figure.align-left, figure.align-right,
table.align-left, table.align-center, table.align-right {
text-align: inherit;
}
/* Text Blocks */
.topic { margin: 1em 2em; }
.sidebar,
.admonition,
.system-message {
margin: 1em 2em;
border: thin solid;
padding: 0.5em 1em;
}
div.line-block { display: block; }
div.line-block div.line-block, pre { margin-left: 2em; }
/* Code line numbers: dropped when copying text from the page */
pre.code .ln { display: none; }
pre.code code:before {
content: attr(data-lineno); /* …, none) fallback not supported by any browser */
color: gray;
}
/* Tables */
table {
border-collapse: collapse;
}
td, th {
border: thin solid silver;
padding: 0 1ex;
}
.borderless td, .borderless th {
border: 0;
padding: 0;
padding-right: 0.5em /* separate table cells */
}
table > caption, figcaption {
text-align: left;
margin-top: 0.2em;
margin-bottom: 0.2em;
}
table.captionbelow {
caption-side: bottom;
}
/* MathML (see "math.css" for --math-output=HTML) */
math .boldsymbol { font-weight: bold; }
math.boxed, math .boxed {padding: 0.25em; border: thin solid; }
/* style table similar to AMS "align" or "aligned" environment: */
mtable.cases > mtr > mtd { text-align: left; }
mtable.ams-align > mtr > mtd { padding-left: 0; padding-right: 0; }
mtable.ams-align > mtr > mtd:nth-child(2n) { text-align: left; }
mtable.ams-align > mtr > mtd:nth-child(2n+1) { text-align: right; }
mtable.ams-align > mtr > mtd:nth-child(2n+3) { padding-left: 2em; }
.mathscr mi, mi.mathscr {
font-family: STIX, XITSMathJax_Script, rsfs10,
"Asana Math", Garamond, cursive;
}
/* Document Header and Footer */
header { border-bottom: 1px solid black; }
footer { border-top: 1px solid black; }
/* Images are block-level by default in Docutils */
/* New HTML5 block elements: set display for older browsers */
img, svg, header, footer, main, aside, nav, section, figure, video, details {
display: block;
}
svg { width: auto; height: auto; } /* enable scaling of SVG images */
/* inline images */
p img, p svg, p video { display: inline; }

View file

@ -0,0 +1,307 @@
/* CSS31_ style sheet for the output of Docutils HTML writers. */
/* Rules for easy reading and pre-defined style variants. */
/* */
/* :Author: Günter Milde, based on html4css1.css by David Goodger */
/* :Id: $Id: plain.css 9615 2024-04-06 13:28:15Z milde $ */
/* :Copyright: © 2015 Günter Milde. */
/* :License: Released under the terms of the `2-Clause BSD license`_, */
/* in short: */
/* */
/* Copying and distribution of this file, with or without modification, */
/* are permitted in any medium without royalty provided the copyright */
/* notice and this notice are preserved. */
/* */
/* This file is offered as-is, without any warranty. */
/* */
/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
/* .. _CSS3: https://www.w3.org/Style/CSS/ */
/* Document Structure */
/* ****************** */
/* "page layout" */
body {
margin: 0;
background-color: #dbdbdb;
--field-indent: 9em; /* default indent of fields in field lists */
}
main, footer, header {
line-height:1.6;
/* avoid long lines --> better reading */
/* optimum is 45…75 characters/line <http://webtypography.net/2.1.2> */
/* OTOH: lines should not be too short because of missing hyphenation, */
max-width: 50rem;
padding: 1px 2%; /* 1px on top avoids grey bar above title (mozilla) */
margin: auto;
}
main {
counter-reset: table figure;
background-color: white;
}
footer, header {
font-size: smaller;
padding: 0.5em 2%;
border: none;
}
/* Table of Contents */
ul.auto-toc > li > p {
padding-left: 1em;
text-indent: -1em;
}
nav.contents ul {
padding-left: 1em;
}
main > nav.contents ul ul ul ul:not(.auto-toc) {
list-style-type: '\2B29\ ';
}
main > nav.contents ul ul ul ul ul:not(.auto-toc) {
list-style-type: '\2B1D\ ';
}
/* Transitions */
hr.docutils {
width: 80%;
margin-top: 1em;
margin-bottom: 1em;
clear: both;
}
/* Paragraphs */
/* vertical space (parskip) */
p, ol, ul, dl, li,
.footnote, .citation,
div > math,
table {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
h1, h2, h3, h4, h5, h6,
dd, details > p:last-child {
margin-bottom: 0.5em;
}
/* Lists */
/* ===== */
/* Definition Lists */
/* Indent lists nested in definition lists */
dd > ul:only-child, dd > ol:only-child { padding-left: 1em; }
/* Description Lists */
/* styled like in most dictionaries, encyclopedias etc. */
dl.description {
display: flow-root;
}
dl.description > dt {
font-weight: bold;
clear: left;
float: left;
margin: 0;
padding: 0;
padding-right: 0.3em;
}
dl.description > dd:after {
display: table;
content: "";
clear: left; /* clearfix for empty descriptions */
}
/* Field Lists */
dl.field-list > dd,
dl.docinfo > dd {
margin-left: var(--field-indent); /* adapted in media queries or HTML */
}
/* example for custom field-name width */
dl.field-list.narrow > dd {
--field-indent: 5em;
}
/* run-in: start field-body on same line after long field names */
dl.field-list.run-in > dd p {
display: block;
}
/* Bibliographic Fields */
/* generally, bibliographic fields use dl.docinfo */
/* but dedication and abstract are placed into divs */
div.abstract p.topic-title {
text-align: center;
}
div.dedication {
margin: 2em 5em;
text-align: center;
font-style: italic;
}
div.dedication p.topic-title {
font-style: normal;
}
/* disclosures */
details { padding-left: 1em; }
summary { margin-left: -1em; }
/* Text Blocks */
/* =========== */
/* Literal Blocks */
pre.literal-block, pre.doctest-block,
pre.math, pre.code {
font-family: monospace;
}
/* Block Quotes and Topics */
bockquote { margin: 1em 2em; }
blockquote p.attribution,
.topic p.attribution {
text-align: right;
margin-left: 20%;
}
/* Tables */
/* ====== */
/* th { vertical-align: bottom; } */
table tr { text-align: left; }
/* "booktabs" style (no vertical lines) */
table.booktabs {
border: 0;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.booktabs * {
border: 0;
}
table.booktabs th {
border-bottom: thin solid;
}
/* numbered tables (counter defined in div.document) */
table.numbered > caption:before {
counter-increment: table;
content: "Table " counter(table) ": ";
font-weight: bold;
}
/* Explicit Markup Blocks */
/* ====================== */
/* Footnotes and Citations */
/* ----------------------- */
/* line on the left */
.footnote-list {
border-left: solid thin;
padding-left: 0.25em;
}
/* Directives */
/* ---------- */
/* Body Elements */
/* ~~~~~~~~~~~~~ */
/* Images and Figures */
/* let content flow to the side of aligned images and figures */
figure.align-left,
img.align-left,
svg.align-left,
video.align-left,
div.align-left,
object.align-left {
clear: left;
float: left;
margin-right: 1em;
}
figure.align-right,
img.align-right,
svg.align-right,
video.align-right,
div.align-right,
object.align-right {
clear: right;
float: right;
margin-left: 1em;
}
/* Stop floating sidebars, images and figures */
h1, h2, h3, h4, footer, header { clear: both; }
/* Numbered figures */
figure.numbered > figcaption > p:before {
counter-increment: figure;
content: "Figure " counter(figure) ": ";
font-weight: bold;
}
/* Admonitions and System Messages */
.caution p.admonition-title,
.attention p.admonition-title,
.danger p.admonition-title,
.error p.admonition-title,
.warning p.admonition-title,
div.error {
color: red;
}
/* Sidebar */
/* Move right. In a layout with fixed margins, */
/* it can be moved into the margin. */
aside.sidebar {
width: 30%;
max-width: 26em;
float: right;
clear: right;
margin-left: 1em;
margin-right: -1%;
background-color: #fffffa;
}
/* Code */
pre.code { padding: 0.7ex }
pre.code, code { background-color: #eeeeee }
/* basic highlighting: for a complete scheme, see */
/* https://docutils.sourceforge.io/sandbox/stylesheets/ */
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
/* Epigraph */
/* Highlights */
/* Pull-Quote */
/* Compound Paragraph */
/* Container */
/* Inline Markup */
/* ============= */
sup, sub { line-height: 0.8; } /* do not add leading for lines with sup/sub */
/* Inline Literals */
/* possible values: normal, nowrap, pre, pre-wrap, pre-line */
/* span.docutils.literal { white-space: pre-wrap; } */
/* Hyperlink References */
a { text-decoration: none; }
/* External Targets */
/* span.target.external */
/* Internal Targets */
/* span.target.internal */
/* Footnote References */
/* a[role="doc-noteref"] */
/* Citation References */
/* a.citation-reference */

View file

@ -0,0 +1,486 @@
/* CSS3_ style sheet for the output of Docutils HTML5 writer. */
/* Generic responsive design for all screen sizes. */
/* */
/* :Author: Günter Milde */
/* */
/* :Id: $Id: responsive.css 9615 2024-04-06 13:28:15Z milde $ */
/* :Copyright: © 2021 Günter Milde. */
/* :License: Released under the terms of the `2-Clause BSD license`_, */
/* in short: */
/* */
/* Copying and distribution of this file, with or without modification, */
/* are permitted in any medium without royalty provided the copyright */
/* notice and this notice are preserved. */
/* */
/* This file is offered as-is, without any warranty. */
/* */
/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
/* .. _CSS3: https://www.w3.org/Style/CSS/ */
/* Note: */
/* This style sheet is provisional: */
/* the API is not settled and may change with any minor Docutils version. */
/* General Settings */
/* ================ */
* { box-sizing: border-box; }
body {
background-color: #fafaf6;
margin: auto;
--field-indent: 6.6em; /* indent of fields in field lists */
--sidebar-margin-right: 0; /* adapted in media queries below */
}
main {
counter-reset: figure table;
}
body > * {
background-color: white;
line-height: 1.6;
padding: 0.5rem calc(29% - 7.2rem); /* go from 5% to 15% (8.15em/54em) */
margin: auto;
max-width: 100rem;
}
sup, sub { /* avoid additional inter-line space for lines with sup/sub */
line-height: 1;
}
/* Vertical Space (Parskip) */
p, ol, ul, dl, li,
.topic,
.footnote, .citation,
div > math,
table {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
h1, h2, h3, h4, h5, h6,
dl > dd, details > p:last-child {
margin-bottom: 0.5em;
}
/* Indented Blocks */
blockquote, figure, .topic {
margin: 1em 2%;
padding-left: 1em;
}
div.line-block div.line-block,
pre, dd, dl.option-list {
margin-left: calc(2% + 1em);
}
/* Object styling */
/* ============== */
footer, header {
font-size: small;
}
/* Frontmatter */
div.dedication {
padding: 0;
margin: 1.4em 0;
font-style: italic;
font-size: large;
}
.dedication p.topic-title {
display: none;
}
blockquote p.attribution,
.topic p.attribution {
text-align: right;
}
/* Table of Contents */
nav.contents ul {
padding-left: 1em;
}
ul.auto-toc > li > p { /* hanging indent */
padding-left: 1em;
text-indent: -1em;
}
main > nav.contents ul:not(.auto-toc) {
list-style-type: square;
}
main > nav.contents ul ul:not(.auto-toc) {
list-style-type: disc;
}
main > nav.contents ul ul ul:not(.auto-toc) {
list-style-type: '\2B29\ ';
}
main > nav.contents ul ul ul ul:not(.auto-toc) {
list-style-type: '\2B1D\ ';
}
main > nav.contents ul ul ul ul ul:not(.auto-toc) {
list-style-type: '\2B2A\ ';
}
nav.contents ul > li::marker {
color: grey;
}
/* Transitions */
hr {
margin: 1em 10%;
}
/* Lists */
dl.field-list.narrow, dl.docinfo, dl.option-list {
--field-indent: 2.4em;
}
ul, ol {
padding-left: 1.1em; /* indent by bullet width (Firefox, DejaVu fonts) */
}
dl.field-list > dd,
dl.docinfo > dd {
margin-left: var(--field-indent); /* adapted in media queries or HTML */
}
dl.option-list > dd {
margin-left: 20%;
}
/* run-in: start field-body on same line after long field names */
dl.field-list.run-in > dd p {
display: block;
}
/* "description style" like in most dictionaries, encyclopedias etc. */
dl.description {
display: flow-root;
}
dl.description > dt {
clear: left;
float: left;
margin: 0;
padding: 0;
padding-right: 0.3em;
font-weight: bold;
}
dl.description > dd:after {
display: table;
content: "";
clear: left; /* clearfix for empty descriptions */
}
/* start lists nested in description/field lists on new line */
dd > dl:first-child,
dd > ul:first-child,
dd > ol:first-child {
clear: left;
}
/* disclosures */
details { padding-left: 1em; }
summary { margin-left: -1em; }
/* Footnotes and Citations */
.footnote {
font-size: small;
}
/* Images, Figures, and Tables */
figcaption,
table > caption {
/* font-size: small; */
font-style: italic;
}
figcaption > .legend {
font-size: small;
font-style: initial;
}
figure.numbered > figcaption > p:before {
counter-increment: figure;
content: "Figure " counter(figure) ": ";
font-weight: bold;
font-style: initial;
}
table tr {
text-align: left;
vertical-align: baseline;
}
table.booktabs { /* "booktabs" style (no vertical lines) */
border-top: 2px solid;
border-bottom: 2px solid;
}
table.booktabs * {
border: 0;
}
table.booktabs th {
border-bottom: thin solid;
}
table.numbered > caption:before {
counter-increment: table;
content: "Table " counter(table) ": ";
font-weight: bold;
font-style: initial;
}
/* Admonitions and System Messages */
.admonition,
div.system-message {
border: thin solid silver;
margin: 1em 2%;
padding: 0.5em 1em;
}
.caution p.admonition-title,
.attention p.admonition-title,
.danger p.admonition-title,
.warning p.admonition-title,
div.error {
color: maroon;
}
div.system-message > p > span.literal {
overflow-wrap: break-word;
}
/* Literal and Code */
pre.literal-block, pre.doctest{
padding: 0.2em;
overflow-x: auto;
}
.literal-block, .doctest, span.literal {
background-color: #f6f9f8;
}
.system-message span.literal {
background-color: inherit;
}
/* basic highlighting: for a complete scheme, see */
/* https://docutils.sourceforge.io/sandbox/stylesheets/ */
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
/* Hyperlink References */
a {
text-decoration: none; /* for chromium */
/* Wrap links at any place, if this is the only way to prevent overflow */
overflow-wrap: break-word;
}
.contents a, a.toc-backref, a.citation-reference {
overflow-wrap: inherit;
}
/* Undecorated Links (see also minimal.css) */
/* a.citation-reference, */
.citation a.fn-backref {
color: inherit;
}
a:hover {
text-decoration: underline;
}
*:hover > a.toc-backref:after,
.topic-title:hover > a:after {
content: " \2191"; /* ↑ UPWARDS ARROW */
color: grey;
}
*:hover > a.self-link:after {
content: "\1F517"; /* LINK SYMBOL */
color: grey;
font-size: smaller;
margin-left: 0.2em;
}
/* highlight specific targets of the current URL */
section:target > h2, section:target > h3, section:target > h4,
section:target > h5, section:target > h6,
span:target + h2, span:target + h3, span:target + h4,
span:target + h5, span:target + h6,
dt:target, span:target,
.contents :target,
.contents:target > .topic-title,
[role="doc-biblioentry"]:target > .label,
[role="doc-biblioref"]:target,
[role="note"]:target, /* Docutils 0.18 ... 0.19 */
[role="doc-footnote"]:target, /* Docutils >= 0.20 */
[role="doc-noteref"]:target {
background-color: #d2e6ec;
}
/* Block Alignment */
/* Let content flow to the side of aligned images and figures */
/* no floats around this elements */
footer, header, hr,
h1, h2, h3 {
clear: both;
}
img.align-left,
svg.align-left,
video.align-left,
figure.align-left,
div.align-left,
table.align-left {
margin-left: 0;
padding-left: 0;
margin-right: 0.5em;
clear: left;
float: left;
}
img.align-right,
svg.align-right,
video.align-right,
figure.align-right,
div.align-right,
table.align-right {
margin-left: 0.5em;
margin-right: 0;
clear: right;
float: right;
}
/* Margin Elements */
/* see below for screen size dependent rules */
.sidebar,
.marginal,
.admonition.marginal {
max-width: 40%;
border: none;
background-color: #efefea;
margin: 0.5em var(--sidebar-margin-right) 0.5em 1em;
padding: 0.5em;
padding-left: 0.7em;
clear: right;
float: right;
font-size: small;
}
.sidebar {
width: 40%;
}
/* Adaptive page layout */
/* ==================== */
@media (max-width: 30em) {
/* Smaller margins and no floating elements for small screens */
/* (main text less than 40 characters/line) */
body > * {
padding: 0.5rem 5%;
line-height: 1.4
}
.sidebar,
.marginal,
.admonition.marginal {
width: auto;
max-width: 100%;
float: none;
}
dl.option-list,
pre {
margin-left: 0;
}
body {
--field-indent: 4em;
}
pre, pre * {
font-size: 0.9em;
/* overflow: auto; */
}
}
@media (min-width: 54em) {
/* Move ToC to the left */
/* Main text width before: 70% ≙ 35em ≙ 75…95 chrs (Dejavu/Times) */
/* after: ≳ 30em ≙ 54…70 chrs (Dejavu/Times) */
body.with-toc {
padding-left: 8%;
}
body.with-toc > * {
margin-left: 0;
padding-left: 22rem; /* fallback for webkit */
padding-left: min(22%, 22rem);
padding-right: 7%;
}
main > nav.contents { /* global ToC */
position: fixed;
top: 0;
left: 0;
width: min(25%, 25em);
height: 100vh;
margin: 0;
background-color: #fafaf6;
padding: 1em 2% 0 2%;
overflow: auto;
}
main > nav.contents > * {
padding-left: 0;
line-height: 1.4;
}
main > nav.contents a {
color: inherit;
}
}
@media (min-width: 70em) {
body {
--field-indent: 9em;
}
}
@media (min-width: 77em) {
/* Move marginalia to 6rem from right border */
/* .sidebar, */
/* .marginal, */
/* .admonition.marginal { */
/* margin-right: calc(6rem - 15%); */
/* } */
/* BUG: margin is calculated for break point width */
/* workaround: variable + many breakpoints */
body > * {
padding-left: 18%;
padding-right: 28%; /* fallback for webkit */
padding-right: min(28%, 28rem);
--sidebar-margin-right: -20rem;
}
/* limit main text to ~ 50em ≙ 85…100 characters DejaVu rsp. …120 Times */
body.with-toc > * {
padding-left: min(22%, 22rem);
padding-right: calc(78% - 50rem); /* fallback for webkit */
padding-right: min(78% - 50rem, 28rem);
--sidebar-margin-right: 0;
}
}
@media (min-width: 85em) {
body.with-toc > * {
--sidebar-margin-right: -9rem;
}
}
@media (min-width: 90em) {
/* move marginalia into the margin */
body > * {
padding-left: min(22%, 22rem);
--sidebar-margin-right: -23rem;
}
body.with-toc > * {
--sidebar-margin-right: -14rem;
}
}
@media (min-width: 99em) {
/* move marginalia out of main text area */
body.with-toc > * {
--sidebar-margin-right: -20rem;
}
body > *, body.with-toc > * { /* for webkit */
padding-left: 22rem;
padding-right: 28rem;
}
.admonition.marginal,
.marginal {
width: 40%; /* make marginal figures, ... "full width" */
}
}
@media (min-width: 104em) {
body.with-toc > * {
--sidebar-margin-right: -23rem;
}
}

View file

@ -0,0 +1,8 @@
%(head_prefix)s
%(head)s
%(stylesheet)s
%(body_prefix)s
%(body_pre_docinfo)s
%(docinfo)s
%(body)s
%(body_suffix)s

View file

@ -0,0 +1,566 @@
/* CSS3_ style sheet for the output of Docutils HTML writers. */
/* Rules inspired by Edward Tufte's layout design. */
/* */
/* :Author: Günter Milde */
/* based on tufte.css_ by Dave Liepmann */
/* and the tufte-latex_ package. */
/* */
/* :Id: $Id: tuftig.css 9503 2023-12-16 22:37:59Z milde $ */
/* :Copyright: © 2020 Günter Milde. */
/* :License: Released under the terms of the `2-Clause BSD license`_, */
/* in short: */
/* */
/* Copying and distribution of this file, with or without modification, */
/* are permitted in any medium without royalty provided the copyright */
/* notice and this notice are preserved. */
/* */
/* This file is offered as-is, without any warranty. */
/* */
/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
/* .. _CSS3: https://www.w3.org/Style/CSS/ */
/* .. _tufte.css: https://edwardtufte.github.io/tufte-css/ */
/* .. _tufte-latex_: https://www.ctan.org/pkg/tufte-latex */
/* General Settings */
/* ================ */
body {
font-family: Georgia, serif;
background-color: #fafaf6;
font-size: 1.2em;
line-height: 1.4;
margin: auto;
}
main {
counter-reset: figure table;
}
main, header, footer {
padding: 0.5em 5%;
background-color: #fefef8;
max-width: 100rem;
}
/* Spacing */
/* vertical space (parskip) */
p, ol, ul, dl, li,
h1, h2, h3, h4, h5, h6,
div.line-block,
.topic,
.footnote, .citation,
table {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
dl > dd {
margin-bottom: 0.5em;
}
/* exceptions */
p:first-child {
margin-top: 0;
}
p:last-child {
margin-bottom: 0;
}
/* Indented Blocks */
blockquote,
.topic {
/* background-color: Honeydew; */
margin: 0.5em 2%;
padding-left: 1em;
}
div.line-block div.line-block,
dl.option-list,
figure > img,
pre.literal-block, pre.math,
pre.doctest-block, pre.code {
/* background-color: LightCyan; */
margin-left: calc(2% + 1em);
}
/* Object styling */
/* ============== */
footer, header {
font-size: smaller;
}
/* Titles and Headings */
h2, h3, h4, p.subtitle, p.section-subtitle,
p.topic-title, p.sidebar-title, p.sidebar-subtitle {
font-weight: normal;
font-style: italic;
text-align: left;
}
.sectnum {
font-style: normal;
}
h1.title {
text-align: left;
margin-top: 2.4em;
margin-bottom: 2em;
font-size: 2.4em;
}
h1 + p.subtitle {
margin-top: -2em;
margin-bottom: 2em;
font-size: 2.0em;
}
section {
margin-top: 2em;
}
h2, .contents > p.topic-title {
font-size: 2.2em;
}
h2 + p.section-subtitle {
font-size: 1.6em;
}
h3 {
font-size: 1.2em;
}
h3 + p.section-subtitle {
font-size: 1.1em;
}
h4 {
font-size: 1em;
}
p.section-subtitle {
font-size: 1em;
}
/* Dedication and Abstract */
div.dedication {
padding: 0;
margin-left: 0;
font-style: italic;
font-size: 1.2em;
}
/* div.abstract p.topic-title, */
div.dedication p.topic-title {
display: none;
}
/* Attribution */
blockquote p.attribution,
.topic p.attribution {
text-align: right;
}
/* Table of Contents */
nav.contents {
padding: 0;
font-style: italic;
}
ul.auto-toc > li > p {
padding-left: 1em;
text-indent: -1em;
}
nav.contents ul {
padding-left: 1em;
}
/* Transitions */
hr {
border: 0;
border-top: 1px solid #ccc;
margin: 1em 10%;
}
/* Lists */
/* Less indent per level */
ul, ol {
padding-left: 1.1em;
}
dd {
margin-left: 1.5em;
}
dd > dl:first-child,
dd > ul:first-child,
dd > ol:first-child {
/* lists nested in definition/description/field lists */
clear: left;
}
dl.field-list > dd,
dl.docinfo > dd,
dl.option-list > dd {
margin-left: 4em;
}
/* example for custom field-name width */
dl.field-list.narrow > dd {
margin-left: 3em;
}
/* run-in: start field-body on same line after long field names */
dl.field-list.run-in > dd p {
display: block;
}
/* italic field name */
dl.description > dt,
dl.field-list > dt,
dl.docinfo > dt {
font-weight: normal;
font-style: italic;
}
/* "description style" like in most dictionaries, encyclopedias etc. */
dl.description > dt {
clear: left;
float: left;
margin: 0;
padding: 0;
padding-right: 0.5em;
}
dl.description > dd:after {
display: block;
content: "";
clear: both;
}
/* Citation list (style as description list) */
.citation-list,
.footnote-list {
display: contents;
}
.citation {
padding-left: 1.5em;
}
.citation .label {
margin-left: -1.5em;
}
/* Images and Figures */
/* Caption to the left (if there is space) or below: */
figure {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
margin: 0.5em 2%;
padding-left: 1em;
}
figure > img,
figure.fullwidth > img {
margin: 0 0.5em 0.5em 0;
padding: 0;
}
figcaption {
font-size: 0.8em;
}
.fullwidth > figcaption {
font-size: inherit;
}
figure.numbered > figcaption > p:before {
counter-increment: figure;
content: "Figure " counter(figure) ": ";
}
/* Tables */
table tr {
text-align: left;
}
/* th { vertical-align: bottom; } */
/* "booktabs" style (no vertical lines) */
table.booktabs {
border-top: 2px solid;
border-bottom: 2px solid;
}
table.booktabs * {
border: 0;
}
table.booktabs th {
border-bottom: thin solid;
}
table.numbered > caption:before {
counter-increment: table;
content: "Table " counter(table) ": ";
}
/* Admonitions and System Messages */
.admonition, .system-message {
border-style: solid;
border-color: silver;
border-width: thin;
margin: 1em 0;
padding: 0.5em;
}
.caution p.admonition-title,
.attention p.admonition-title,
.danger p.admonition-title,
.warning p.admonition-title,
div.error {
color: maroon;
}
/* Literal and Code */
pre.literal-block, pre.doctest-block,
pre.math, pre.code {
/* font-family: Consolas, "Liberation Mono", Menlo, monospace; */
/* font-size: 0.9em; */
overflow: auto;
}
/* basic highlighting: for a complete scheme, see */
/* https://docutils.sourceforge.io/sandbox/stylesheets/ */
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
.sans {
font-family: "Gill Sans", "Gill Sans MT", Calibri, "Lucida Sans", "Noto Sans", sans-serif;
letter-spacing: .02em;
}
/* Hyperlink References */
/* underline that clears descenders */
a {
color: inherit;
}
a:link {
text-decoration: underline;
/* text-decoration-skip-ink: auto; nonstandard selector */
}
/* undecorated links */
.contents a:link, a.toc-backref:link, a.image-reference:link,
a[role="doc-noteref"]:link, a[role="doc-backlink"]:link, .backrefs a:link,
a.citation-reference:link,
a[href^="#system-message"] {
text-decoration: none;
}
a:link:hover {
text-decoration: underline;
}
/* Block Alignment */
/* Let content flow to the side of aligned images and figures */
/* (does not work if the image/figure is a grid element). */
/* no floats around this elements */
footer, header,
hr.docutils,
h1, h2, h3, .contents > p.topic-title,
.fullwidth {
clear: both;
}
img.align-left,
svg.align-left,
video.align-left,
figure.align-left,
div.align-left,
table.align-left {
margin-left: 0;
padding-left: 0;
padding-right: 0.5em;
clear: left;
float: left;
}
figure.align-left > img {
margin-left: 0;
padding-left: 0;
}
img.align-right,
svg.align-right,
video.align-right,
div.align-right {
padding-left: 0.5em;
clear: right;
float: right;
}
figure.align-right {
clear: right;
float: right;
}
figure.align-right > img {
justify-self: right;
padding: 0;
}
table.align-right {
margin-right: 2.5%;
}
figure.align-center {
align-content: center;
justify-content: center;
}
figure.align-center > img {
padding-left: 0;
justify-self: center;
}
/* Margin Elements */
/* see below for screen size dependent rules */
aside.sidebar,
.marginal,
.admonition.marginal,
.topic.marginal {
background-color: #efefea;
box-sizing: border-box;
margin-left: 2%;
margin-right: 0;
padding: 0.5em;
font-size: 0.8em;
}
aside.sidebar {
background-color: inherit;
}
figure.marginal > figcaption {
font-size: 1em;
}
.footnote {
font-size: smaller;
overflow: auto;
}
/* Adaptive page layout */
/* no floating for very small Screens */
/* (main text up to ca. 40 characters/line) */
@media (min-width: 35em) {
main, header, footer {
padding: 0.5em calc(15% - 3rem);
line-height: 1.6
}
aside.sidebar,
.marginal,
.admonition.marginal,
.topic.marginal {
max-width: 45%;
float: right;
clear: right;
}
dl.field-list > dd,
dl.docinfo > dd {
margin-left: 6em;
}
dl.option-list > dd {
margin-left: 6em;
}
}
/* 2 column layout with wide margin */
@media (min-width: 65em) {
/* use the same grid for main, all sections, and figures */
main, section {
display: grid;
grid-template-columns: [content] minmax(0, 6fr)
[margin] 3fr [end];
grid-column-gap: calc(3em + 1%);
}
main > section, section > section {
grid-column: 1 / end;
}
main, header, footer {
padding-right: 5%; /* less padding right of margin-column */
}
section > figure {
display: contents; /* to place caption in the margin */
}
/* Main text elements */
main > *, section > *,
figure > img,
.footnote.align-left, /* override the placement in the margin */
.citation.align-left {
grid-column: content;
}
.citation.align-left {
font-size: 1em;
padding-left: 1.5em;
}
.citation.align-left .label {
margin-left: -1.5em;
}
figure > img { /* indent */
margin: 0.5em 2%;
padding-left: 1em;
}
/* Margin Elements */
/* Sidebar, Footnotes, Citations, Captions */
aside.sidebar,
.citation,
.footnote,
figcaption,
/* table > caption, does not work :(*/
.marginal,
.admonition.marginal,
.topic.marginal {
/* color: red; */
grid-column: margin;
width: auto;
max-width: 55em;
margin: 0.5em 0;
border: none;
padding: 0;
font-size: 0.8em;
text-align: initial; /* overwrite align-* */
background-color: inherit;
}
.admonition.marginal {
padding: 0.5em;
}
figure.marginal {
display: block;
margin: 0.5em 0;
}
.citation,
.footnote {
padding-left: 0;
}
.citation .label,
.footnote .label {
margin-left: 0;
}
/* Fullwidth Elements */
h1.title, p.subtitle,
dl.docinfo,
div.abstract,
div.dedication,
nav.contents,
aside.system-message,
pre,
.fullwidth,
.fullwidth img,
.fullwidth figcaption {
/* background-color: Linen; */
grid-column: content / end;
margin-right: calc(10% - 3rem);
max-width: 55em;
}
}
/* 3 column layout */
@media (min-width: 100em) {
main, header, footer {
padding-left: 30%;
}
main > nav.contents {
position: fixed;
top: 0;
left: 0;
box-sizing: border-box;
width: 25%;
height: 100vh;
margin: 0;
background-color: #fafaf6;
padding: 5.5em 2%;
overflow: auto;
}
main > nav.contents > * {
padding-left: 0;
}
}
/* wrap URLs */
/* a:link { */
/* white-space: normal; */
/* hyphens: none; */
/* } */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,14 @@
$head_prefix% generated by Docutils <https://docutils.sourceforge.io/>
\usepackage{cmap} % fix search and cut-and-paste in Acrobat
$requirements
%%% Custom LaTeX preamble
$latex_preamble
%%% User specified packages and stylesheets
$stylesheet
%%% Fallback definitions for Docutils-specific commands
$fallbacks
$pdfsetup
%%% Body
\begin{document}
$titledata$body_pre_docinfo$docinfo$dedication$abstract$body
\end{document}

View file

@ -0,0 +1,223 @@
%% docutils.sty: macros for Docutils LaTeX output.
%%
%% Copyright © 2020 Günter Milde
%% Released under the terms of the `2-Clause BSD license`, in short:
%%
%% Copying and distribution of this file, with or without modification,
%% are permitted in any medium without royalty provided the copyright
%% notice and this notice are preserved.
%% This file is offered as-is, without any warranty.
% .. include:: README.md
%
% Implementation
% ==============
%
% ::
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{docutils}
[2021/05/18 macros for Docutils LaTeX output]
% Helpers
% -------
%
% duclass::
% class handling for environments (block-level elements)
% \begin{DUclass}{spam} tries \DUCLASSspam and
% \end{DUclass}{spam} tries \endDUCLASSspam
\ifx\DUclass\undefined % poor man's "provideenvironment"
\newenvironment{DUclass}[1]%
{% "#1" does not work in end-part of environment.
\def\DocutilsClassFunctionName{DUCLASS#1}
\csname \DocutilsClassFunctionName \endcsname}%
{\csname end\DocutilsClassFunctionName \endcsname}%
\fi
% providelength::
% Provide a length variable and set default, if it is new
\providecommand*{\DUprovidelength}[2]{
\ifthenelse{\isundefined{#1}}{\newlength{#1}\setlength{#1}{#2}}{}
}
% Configuration defaults
% ----------------------
%
% See `Docutils LaTeX Writer`_ for details.
%
% abstract::
\providecommand*{\DUCLASSabstract}{
\renewcommand{\DUtitle}[1]{\centerline{\textbf{##1}}}
}
% dedication::
% special topic for dedications
\providecommand*{\DUCLASSdedication}{%
\renewenvironment{quote}{\begin{center}}{\end{center}}%
}
% TODO: add \em to set dedication text in italics?
%
% docinfo::
% width of docinfo table
\DUprovidelength{\DUdocinfowidth}{0.9\linewidth}
% error::
\providecommand*{\DUCLASSerror}{\color{red}}
% highlight_rules::
% basic code highlight:
\providecommand*\DUrolecomment[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}}
\providecommand*\DUroledeleted[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}}
\providecommand*\DUrolekeyword[1]{\textbf{#1}}
\providecommand*\DUrolestring[1]{\textit{#1}}
% Elements
% --------
%
% Definitions for unknown or to-be-configured Docutils elements.
%
% admonition::
% admonition environment (specially marked topic)
\ifx\DUadmonition\undefined % poor man's "provideenvironment"
\newbox{\DUadmonitionbox}
\newenvironment{DUadmonition}%
{\begin{center}
\begin{lrbox}{\DUadmonitionbox}
\begin{minipage}{0.9\linewidth}
}%
{ \end{minipage}
\end{lrbox}
\fbox{\usebox{\DUadmonitionbox}}
\end{center}
}
\fi
% fieldlist::
% field list environment (for separate configuration of `field lists`)
\ifthenelse{\isundefined{\DUfieldlist}}{
\newenvironment{DUfieldlist}%
{\quote\description}
{\enddescription\endquote}
}{}
% footnotes::
% numerical or symbol footnotes with hyperlinks and backlinks
\providecommand*{\DUfootnotemark}[3]{%
\raisebox{1em}{\hypertarget{#1}{}}%
\hyperlink{#2}{\textsuperscript{#3}}%
}
\providecommand{\DUfootnotetext}[4]{%
\begingroup%
\renewcommand{\thefootnote}{%
\protect\raisebox{1em}{\protect\hypertarget{#1}{}}%
\protect\hyperlink{#2}{#3}}%
\footnotetext{#4}%
\endgroup%
}
% inline::
% custom inline roles: \DUrole{#1}{#2} tries \DUrole#1{#2}
\providecommand*{\DUrole}[2]{%
\ifcsname DUrole#1\endcsname%
\csname DUrole#1\endcsname{#2}%
\else%
#2%
\fi%
}
% legend::
% legend environment (in figures and formal tables)
\ifthenelse{\isundefined{\DUlegend}}{
\newenvironment{DUlegend}{\small}{}
}{}
% lineblock::
% line block environment
\DUprovidelength{\DUlineblockindent}{2.5em}
\ifthenelse{\isundefined{\DUlineblock}}{
\newenvironment{DUlineblock}[1]{%
\list{}{\setlength{\partopsep}{\parskip}
\addtolength{\partopsep}{\baselineskip}
\setlength{\topsep}{0pt}
\setlength{\itemsep}{0.15\baselineskip}
\setlength{\parsep}{0pt}
\setlength{\leftmargin}{#1}}
\raggedright
}
{\endlist}
}{}
% optionlist::
% list of command line options
\providecommand*{\DUoptionlistlabel}[1]{\bfseries #1 \hfill}
\DUprovidelength{\DUoptionlistindent}{3cm}
\ifthenelse{\isundefined{\DUoptionlist}}{
\newenvironment{DUoptionlist}{%
\list{}{\setlength{\labelwidth}{\DUoptionlistindent}
\setlength{\rightmargin}{1cm}
\setlength{\leftmargin}{\rightmargin}
\addtolength{\leftmargin}{\labelwidth}
\addtolength{\leftmargin}{\labelsep}
\renewcommand{\makelabel}{\DUoptionlistlabel}}
}
{\endlist}
}{}
% rubric::
% informal heading
\providecommand*{\DUrubric}[1]{\subsubsection*{\emph{#1}}}
% sidebar::
% text outside the main text flow
\providecommand{\DUsidebar}[1]{%
\begin{center}
\colorbox[gray]{0.80}{\parbox{0.9\linewidth}{#1}}
\end{center}
}
% title::
% title for topics, admonitions, unsupported section levels, and sidebar
\providecommand*{\DUtitle}[1]{%
\smallskip\noindent\textbf{#1}\smallskip}
% subtitle::
% subtitle (for sidebar)
\providecommand*{\DUsubtitle}[1]{\par\emph{#1}\smallskip}
% documentsubtitle::
% subtitle (in document title)
\providecommand*{\DUdocumentsubtitle}[1]{{\large #1}}
% titlereference::
% titlereference standard role
\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
% transition::
% transition (break / fancybreak / anonymous section)
\providecommand*{\DUtransition}{%
\hspace*{\fill}\hrulefill\hspace*{\fill}
\vskip 0.5\baselineskip
}

View file

@ -0,0 +1,19 @@
% generated by Docutils <https://docutils.sourceforge.io/>
$head_prefix
\usepackage{cmap} % fix search and cut-and-paste in Acrobat
$requirements
%%% Custom LaTeX preamble
$latex_preamble
%%% User specified packages and stylesheets
$stylesheet
%%% Fallback definitions for Docutils-specific commands
$fallbacks$pdfsetup
$titledata
%%% Body
\begin{document}
\begin{titlepage}
$body_pre_docinfo$docinfo$dedication$abstract
\thispagestyle{empty}
\end{titlepage}
$body
\end{document}

View file

@ -0,0 +1,18 @@
% generated by Docutils <https://docutils.sourceforge.io/>
$head_prefix
$requirements
%%% Custom LaTeX preamble
$latex_preamble
%%% User specified packages and stylesheets
$stylesheet
%%% Fallback definitions for Docutils-specific commands
$fallbacks$pdfsetup
$titledata
%%% Body
\begin{document}
\begin{titlingpage}
\thispagestyle{empty}
$body_pre_docinfo$docinfo$dedication$abstract
\end{titlingpage}
$body
\end{document}

View file

@ -0,0 +1,21 @@
$head_prefix% generated by Docutils <https://docutils.sourceforge.io/>
% rubber: set program xelatex
\usepackage{fontspec}
% \defaultfontfeatures{Scale=MatchLowercase}
% straight double quotes (defined T1 but missing in TU):
\ifdefined \UnicodeEncodingName
\DeclareTextCommand{\textquotedbl}{\UnicodeEncodingName}{%
{\addfontfeatures{RawFeature=-tlig,Mapping=}\char34}}%
\fi
$requirements
%%% Custom LaTeX preamble
$latex_preamble
%%% User specified packages and stylesheets
$stylesheet
%%% Fallback definitions for Docutils-specific commands
$fallbacks$pdfsetup
$titledata
%%% Body
\begin{document}
$body_pre_docinfo$docinfo$dedication$abstract$body
\end{document}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,25 @@
# $Id: null.py 9352 2023-04-17 20:26:41Z milde $
# Author: David Goodger <goodger@python.org>
# Copyright: This module has been placed in the public domain.
"""
A do-nothing Writer.
`self.output` will change from ``None`` to the empty string
in Docutils 0.22.
"""
from docutils import writers
class Writer(writers.UnfilteredWriter):
supported = ('null',)
"""Formats this writer supports."""
config_section = 'null writer'
config_section_dependencies = ('writers',)
def translate(self):
# output = None # TODO in 0.22
pass

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,78 @@
#!/usr/bin/env python3
# $Id: prepstyles.py 9386 2023-05-16 14:49:31Z milde $
# Author: Dave Kuhlman <dkuhlman@rexx.com>
# Copyright: This module has been placed in the public domain.
"""
Adapt a word-processor-generated styles.odt for odtwriter use:
Drop page size specifications from styles.xml in STYLE_FILE.odt.
See https://docutils.sourceforge.io/docs/user/odt.html#page-size
"""
# Author: Michael Schutte <michi@uiae.at>
from xml.etree import ElementTree as etree
import sys
import zipfile
from tempfile import mkstemp
import shutil
import os
NAMESPACES = {
"style": "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
"fo": "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
}
def prepstyle(filename):
zin = zipfile.ZipFile(filename)
styles = zin.open("styles.xml")
root = None
# some extra effort to preserve namespace prefixes
for event, elem in etree.iterparse(styles, events=("start", "start-ns")):
if event == "start-ns":
etree.register_namespace(elem[0], elem[1])
elif event == "start":
if root is None:
root = elem
styles.close()
for el in root.findall(".//style:page-layout-properties",
namespaces=NAMESPACES):
for attr in list(el.attrib):
if attr.startswith("{%s}" % NAMESPACES["fo"]):
del el.attrib[attr]
tempname = mkstemp()
zout = zipfile.ZipFile(os.fdopen(tempname[0], "wb"), "w",
zipfile.ZIP_DEFLATED)
for item in zin.infolist():
if item.filename == "styles.xml":
zout.writestr(item, etree.tostring(root, encoding="UTF-8"))
else:
zout.writestr(item, zin.read(item.filename))
zout.close()
zin.close()
shutil.move(tempname[1], filename)
def main():
args = sys.argv[1:]
if len(args) != 1 or args[0] in ('-h', '--help'):
print(__doc__, file=sys.stderr)
print("Usage: %s STYLE_FILE.odt\n" % sys.argv[0], file=sys.stderr)
sys.exit(1)
filename = args[0]
prepstyle(filename)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,109 @@
# $Id: pygmentsformatter.py 9015 2022-03-03 22:15:00Z milde $
# Author: Dave Kuhlman <dkuhlman@rexx.com>
# Copyright: This module has been placed in the public domain.
"""
Additional support for Pygments formatter.
"""
import pygments
import pygments.formatter
class OdtPygmentsFormatter(pygments.formatter.Formatter):
def __init__(self, rststyle_function, escape_function):
pygments.formatter.Formatter.__init__(self)
self.rststyle_function = rststyle_function
self.escape_function = escape_function
def rststyle(self, name, parameters=()):
return self.rststyle_function(name, parameters)
class OdtPygmentsProgFormatter(OdtPygmentsFormatter):
def format(self, tokensource, outfile):
tokenclass = pygments.token.Token
for ttype, value in tokensource:
value = self.escape_function(value)
if ttype == tokenclass.Keyword:
s2 = self.rststyle('codeblock-keyword')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype == tokenclass.Literal.String:
s2 = self.rststyle('codeblock-string')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype in (
tokenclass.Literal.Number.Integer,
tokenclass.Literal.Number.Integer.Long,
tokenclass.Literal.Number.Float,
tokenclass.Literal.Number.Hex,
tokenclass.Literal.Number.Oct,
tokenclass.Literal.Number,
):
s2 = self.rststyle('codeblock-number')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype == tokenclass.Operator:
s2 = self.rststyle('codeblock-operator')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype == tokenclass.Comment:
s2 = self.rststyle('codeblock-comment')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype == tokenclass.Name.Class:
s2 = self.rststyle('codeblock-classname')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype == tokenclass.Name.Function:
s2 = self.rststyle('codeblock-functionname')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype == tokenclass.Name:
s2 = self.rststyle('codeblock-name')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
else:
s1 = value
outfile.write(s1)
class OdtPygmentsLaTeXFormatter(OdtPygmentsFormatter):
def format(self, tokensource, outfile):
tokenclass = pygments.token.Token
for ttype, value in tokensource:
value = self.escape_function(value)
if ttype == tokenclass.Keyword:
s2 = self.rststyle('codeblock-keyword')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype in (tokenclass.Literal.String,
tokenclass.Literal.String.Backtick,
):
s2 = self.rststyle('codeblock-string')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype == tokenclass.Name.Attribute:
s2 = self.rststyle('codeblock-operator')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype == tokenclass.Comment:
if value[-1] == '\n':
s2 = self.rststyle('codeblock-comment')
s1 = '<text:span text:style-name="%s">%s</text:span>\n' % \
(s2, value[:-1], )
else:
s2 = self.rststyle('codeblock-comment')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
elif ttype == tokenclass.Name.Builtin:
s2 = self.rststyle('codeblock-name')
s1 = '<text:span text:style-name="%s">%s</text:span>' % \
(s2, value, )
else:
s1 = value
outfile.write(s1)

View file

@ -0,0 +1,101 @@
# $Id: __init__.py 9541 2024-02-17 10:37:13Z milde $
# Author: David Goodger <goodger@python.org>
# Copyright: This module has been placed in the public domain.
"""
PEP HTML Writer.
"""
__docformat__ = 'reStructuredText'
import os
import os.path
from docutils import frontend, nodes, utils
from docutils.writers import html4css1
class Writer(html4css1.Writer):
default_stylesheet = 'pep.css'
default_stylesheet_path = utils.relative_path(
os.path.join(os.getcwd(), 'dummy'),
os.path.join(os.path.dirname(__file__), default_stylesheet))
default_template = 'template.txt'
default_template_path = utils.relative_path(
os.path.join(os.getcwd(), 'dummy'),
os.path.join(os.path.dirname(__file__), default_template))
settings_spec = html4css1.Writer.settings_spec + (
'PEP/HTML Writer Options',
'For the PEP/HTML writer, the default value for the --stylesheet-path '
'option is "%s", and the default value for --template is "%s". '
'See HTML Writer Options above.'
% (default_stylesheet_path, default_template_path),
(('Python\'s home URL. Default is "https://www.python.org".',
['--python-home'],
{'default': 'https://www.python.org', 'metavar': '<URL>'}),
('Home URL prefix for PEPs. Default is "." (current directory).',
['--pep-home'],
{'default': '.', 'metavar': '<URL>'}),
# For testing.
(frontend.SUPPRESS_HELP,
['--no-random'],
{'action': 'store_true', 'validator': frontend.validate_boolean}),))
settings_default_overrides = {'stylesheet_path': default_stylesheet_path,
'template': default_template_path}
relative_path_settings = ('template',)
config_section = 'pep_html writer'
config_section_dependencies = ('writers', 'html writers',
'html4css1 writer')
def __init__(self):
html4css1.Writer.__init__(self)
self.translator_class = HTMLTranslator
def interpolation_dict(self):
subs = html4css1.Writer.interpolation_dict(self)
settings = self.document.settings
pyhome = settings.python_home
subs['pyhome'] = pyhome
subs['pephome'] = settings.pep_home
if pyhome == '..':
subs['pepindex'] = '.'
else:
subs['pepindex'] = pyhome + '/dev/peps'
index = self.document.first_child_matching_class(nodes.field_list)
header = self.document[index]
self.pepnum = header[0][1].astext()
subs['pep'] = self.pepnum
if settings.no_random:
subs['banner'] = 0
else:
import random
subs['banner'] = random.randrange(64)
try:
subs['pepnum'] = '%04i' % int(self.pepnum)
except ValueError:
subs['pepnum'] = self.pepnum
self.title = header[1][1].astext()
subs['title'] = self.title
subs['body'] = ''.join(
self.body_pre_docinfo + self.docinfo + self.body)
return subs
def assemble_parts(self):
html4css1.Writer.assemble_parts(self)
self.parts['title'] = [self.title]
self.parts['pepnum'] = self.pepnum
class HTMLTranslator(html4css1.HTMLTranslator):
def depart_field_list(self, node):
html4css1.HTMLTranslator.depart_field_list(self, node)
if 'rfc2822' in node['classes']:
self.body.append('<hr />\n')

View file

@ -0,0 +1,344 @@
/*
:Author: David Goodger
:Contact: goodger@python.org
:date: $Date: 2022-01-29 23:26:10 +0100 (Sa, 29. Jän 2022) $
:version: $Revision: 8995 $
:copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the PEP HTML output of Docutils.
*/
/* "! important" is used here to override other ``margin-top`` and
``margin-bottom`` styles that are later in the stylesheet or
more specific. See http://www.w3.org/TR/CSS1#the-cascade */
.first {
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.navigation {
width: 100% ;
background: #99ccff ;
margin-top: 0px ;
margin-bottom: 0px }
.navigation .navicon {
width: 150px ;
height: 35px }
.navigation .textlinks {
padding-left: 1em ;
text-align: left }
.navigation td, .navigation th {
padding-left: 0em ;
padding-right: 0em ;
vertical-align: middle }
.rfc2822 {
margin-top: 0.5em ;
margin-left: 0.5em ;
margin-right: 0.5em ;
margin-bottom: 0em }
.rfc2822 td {
text-align: left }
.rfc2822 th.field-name {
text-align: right ;
font-family: sans-serif ;
padding-right: 0.5em ;
font-weight: bold ;
margin-bottom: 0em }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
body {
margin: 0px ;
margin-bottom: 1em ;
padding: 0px }
dl.docutils dd {
margin-bottom: 0.5em }
div.section {
margin-left: 1em ;
margin-right: 1em ;
margin-bottom: 1.5em }
div.section div.section {
margin-left: 0em ;
margin-right: 0em ;
margin-top: 1.5em }
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.footer {
margin-left: 1em ;
margin-right: 1em }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin-left: 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1 {
font-family: sans-serif ;
font-size: large }
h2 {
font-family: sans-serif ;
font-size: medium }
h3 {
font-family: sans-serif ;
font-size: small }
h4 {
font-family: sans-serif ;
font-style: italic ;
font-size: small }
h5 {
font-family: sans-serif;
font-size: x-small }
h6 {
font-family: sans-serif;
font-style: italic ;
font-size: x-small }
hr.docutils {
width: 75% }
img.align-left {
clear: left }
img.align-right {
clear: right }
img.borderless {
border: 0 }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-family: sans-serif ;
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font-family: serif ;
font-size: 100% }
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.option-argument {
font-style: italic }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
td.num {
text-align: right }
th.field-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="%(encoding)s"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!--
This HTML is auto-generated. DO NOT EDIT THIS FILE! If you are writing a new
PEP, see http://peps.python.org/pep-0001 for instructions and links
to templates. DO NOT USE THIS HTML FILE AS YOUR TEMPLATE!
-->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=%(encoding)s" />
<meta name="generator" content="Docutils %(version)s: https://docutils.sourceforge.io/" />
<title>PEP %(pep)s - %(title)s</title>
%(stylesheet)s
</head>
<body bgcolor="white">
<div class="header">
<strong>Python Enhancement Proposals</strong>
| <a href="%(pyhome)s/">Python</a>
&raquo; <a href="https://peps.python.org/pep-0000/">PEP Index</a>
&raquo; PEP %(pep)s &ndash; %(title)s
<hr class="header"/>
</div>
<div class="document">
%(body)s
%(body_suffix)s

View file

@ -0,0 +1,40 @@
# $Id: pseudoxml.py 9043 2022-03-11 12:09:16Z milde $
# Author: David Goodger <goodger@python.org>
# Copyright: This module has been placed in the public domain.
"""
Simple internal document tree Writer, writes indented pseudo-XML.
"""
__docformat__ = 'reStructuredText'
from docutils import writers, frontend
class Writer(writers.Writer):
supported = ('pseudoxml', 'pprint', 'pformat')
"""Formats this writer supports."""
settings_spec = (
'"Docutils pseudo-XML" Writer Options',
None,
(('Pretty-print <#text> nodes.',
['--detailed'],
{'action': 'store_true', 'validator': frontend.validate_boolean}),
)
)
config_section = 'pseudoxml writer'
config_section_dependencies = ('writers',)
output = None
"""Final translated form of `document`."""
def translate(self):
self.output = self.document.pformat()
def supports(self, format):
"""This writer supports all format-specific elements."""
return True

View file

@ -0,0 +1,353 @@
# $Id: __init__.py 9542 2024-02-17 10:37:23Z milde $
# Authors: Chris Liechti <cliechti@gmx.net>;
# David Goodger <goodger@python.org>
# Copyright: This module has been placed in the public domain.
"""
S5/HTML Slideshow Writer.
"""
__docformat__ = 'reStructuredText'
import sys
import os
import re
import docutils
from docutils import frontend, nodes, utils
from docutils.writers import html4css1
themes_dir_path = utils.relative_path(
os.path.join(os.getcwd(), 'dummy'),
os.path.join(os.path.dirname(__file__), 'themes'))
def find_theme(name):
# Where else to look for a theme?
# Check working dir? Destination dir? Config dir? Plugins dir?
path = os.path.join(themes_dir_path, name)
if not os.path.isdir(path):
raise docutils.ApplicationError(
'Theme directory not found: %r (path: %r)' % (name, path))
return path
class Writer(html4css1.Writer):
settings_spec = html4css1.Writer.settings_spec + (
'S5 Slideshow Specific Options',
'For the S5/HTML writer, the --no-toc-backlinks option '
'(defined in General Docutils Options above) is the default, '
'and should not be changed.',
(('Specify an installed S5 theme by name. Overrides --theme-url. '
'The default theme name is "default". The theme files will be '
'copied into a "ui/<theme>" directory, in the same directory as the '
'destination file (output HTML). Note that existing theme files '
'will not be overwritten (unless --overwrite-theme-files is used).',
['--theme'],
{'default': 'default', 'metavar': '<name>',
'overrides': 'theme_url'}),
('Specify an S5 theme URL. The destination file (output HTML) will '
'link to this theme; nothing will be copied. Overrides --theme.',
['--theme-url'],
{'metavar': '<URL>', 'overrides': 'theme'}),
('Allow existing theme files in the ``ui/<theme>`` directory to be '
'overwritten. The default is not to overwrite theme files.',
['--overwrite-theme-files'],
{'action': 'store_true', 'validator': frontend.validate_boolean}),
('Keep existing theme files in the ``ui/<theme>`` directory; do not '
'overwrite any. This is the default.',
['--keep-theme-files'],
{'dest': 'overwrite_theme_files', 'action': 'store_false'}),
('Set the initial view mode to "slideshow" [default] or "outline".',
['--view-mode'],
{'choices': ['slideshow', 'outline'], 'default': 'slideshow',
'metavar': '<mode>'}),
('Normally hide the presentation controls in slideshow mode. '
'This is the default.',
['--hidden-controls'],
{'action': 'store_true', 'default': True,
'validator': frontend.validate_boolean}),
('Always show the presentation controls in slideshow mode. '
'The default is to hide the controls.',
['--visible-controls'],
{'dest': 'hidden_controls', 'action': 'store_false'}),
('Enable the current slide indicator ("1 / 15"). '
'The default is to disable it.',
['--current-slide'],
{'action': 'store_true', 'validator': frontend.validate_boolean}),
('Disable the current slide indicator. This is the default.',
['--no-current-slide'],
{'dest': 'current_slide', 'action': 'store_false'}),))
settings_default_overrides = {'toc_backlinks': 0}
config_section = 's5_html writer'
config_section_dependencies = ('writers', 'html writers',
'html4css1 writer')
def __init__(self):
html4css1.Writer.__init__(self)
self.translator_class = S5HTMLTranslator
class S5HTMLTranslator(html4css1.HTMLTranslator):
s5_stylesheet_template = """\
<!-- configuration parameters -->
<meta name="defaultView" content="%(view_mode)s" />
<meta name="controlVis" content="%(control_visibility)s" />
<!-- style sheet links -->
<script src="%(path)s/slides.js" type="text/javascript"></script>
<link rel="stylesheet" href="%(path)s/slides.css"
type="text/css" media="projection" id="slideProj" />
<link rel="stylesheet" href="%(path)s/outline.css"
type="text/css" media="screen" id="outlineStyle" />
<link rel="stylesheet" href="%(path)s/print.css"
type="text/css" media="print" id="slidePrint" />
<link rel="stylesheet" href="%(path)s/opera.css"
type="text/css" media="projection" id="operaFix" />\n"""
# The script element must go in front of the link elements to
# avoid a flash of unstyled content (FOUC), reproducible with
# Firefox.
disable_current_slide = """
<style type="text/css">
#currentSlide {display: none;}
</style>\n"""
layout_template = """\
<div class="layout">
<div id="controls"></div>
<div id="currentSlide"></div>
<div id="header">
%(header)s
</div>
<div id="footer">
%(title)s%(footer)s
</div>
</div>\n"""
# <div class="topleft"></div>
# <div class="topright"></div>
# <div class="bottomleft"></div>
# <div class="bottomright"></div>
default_theme = 'default'
"""Name of the default theme."""
base_theme_file = '__base__'
"""Name of the file containing the name of the base theme."""
direct_theme_files = (
'slides.css', 'outline.css', 'print.css', 'opera.css', 'slides.js')
"""Names of theme files directly linked to in the output HTML"""
indirect_theme_files = (
's5-core.css', 'framing.css', 'pretty.css')
"""Names of files used indirectly; imported or used by files in
`direct_theme_files`."""
required_theme_files = indirect_theme_files + direct_theme_files
"""Names of mandatory theme files."""
def __init__(self, *args):
html4css1.HTMLTranslator.__init__(self, *args)
# insert S5-specific stylesheet and script stuff:
self.theme_file_path = None
try:
self.setup_theme()
except docutils.ApplicationError as e:
self.document.reporter.warning(e)
view_mode = self.document.settings.view_mode
control_visibility = ('visible', 'hidden')[self.document.settings
.hidden_controls]
self.stylesheet.append(self.s5_stylesheet_template
% {'path': self.theme_file_path,
'view_mode': view_mode,
'control_visibility': control_visibility})
if not self.document.settings.current_slide:
self.stylesheet.append(self.disable_current_slide)
self.meta.append('<meta name="version" content="S5 1.1" />\n')
self.s5_footer = []
self.s5_header = []
self.section_count = 0
self.theme_files_copied = None
def setup_theme(self):
if self.document.settings.theme:
self.copy_theme()
elif self.document.settings.theme_url:
self.theme_file_path = self.document.settings.theme_url
else:
raise docutils.ApplicationError(
'No theme specified for S5/HTML writer.')
def copy_theme(self):
"""
Locate & copy theme files.
A theme may be explicitly based on another theme via a '__base__'
file. The default base theme is 'default'. Files are accumulated
from the specified theme, any base themes, and 'default'.
"""
settings = self.document.settings
path = find_theme(settings.theme)
theme_paths = [path]
self.theme_files_copied = {}
required_files_copied = {}
# This is a link (URL) in HTML, so we use "/", not os.sep:
self.theme_file_path = 'ui/%s' % settings.theme
if not settings.output:
raise docutils.ApplicationError(
'Output path not specified, you may need to copy'
' the S5 theme files "by hand" or set the "--output" option.')
dest = os.path.join(
os.path.dirname(settings.output), 'ui', settings.theme)
if not os.path.isdir(dest):
os.makedirs(dest)
default = False
while path:
for f in os.listdir(path): # copy all files from each theme
if f == self.base_theme_file:
continue # ... except the "__base__" file
if (self.copy_file(f, path, dest)
and f in self.required_theme_files):
required_files_copied[f] = True
if default:
break # "default" theme has no base theme
# Find the "__base__" file in theme directory:
base_theme_file = os.path.join(path, self.base_theme_file)
# If it exists, read it and record the theme path:
if os.path.isfile(base_theme_file):
with open(base_theme_file, encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
line = line.strip()
if line and not line.startswith('#'):
path = find_theme(line)
if path in theme_paths: # check for duplicates/cycles
path = None # if found, use default base
else:
theme_paths.append(path)
break
else: # no theme name found
path = None # use default base
else: # no base theme file found
path = None # use default base
if not path:
path = find_theme(self.default_theme)
theme_paths.append(path)
default = True
if len(required_files_copied) != len(self.required_theme_files):
# Some required files weren't found & couldn't be copied.
required = list(self.required_theme_files)
for f in required_files_copied.keys():
required.remove(f)
raise docutils.ApplicationError(
'Theme files not found: %s'
% ', '.join('%r' % f for f in required))
files_to_skip_pattern = re.compile(r'~$|\.bak$|#$|\.cvsignore$')
def copy_file(self, name, source_dir, dest_dir):
"""
Copy file `name` from `source_dir` to `dest_dir`.
Return True if the file exists in either `source_dir` or `dest_dir`.
"""
source = os.path.join(source_dir, name)
dest = os.path.join(dest_dir, name)
if dest in self.theme_files_copied:
return True
else:
self.theme_files_copied[dest] = True
if os.path.isfile(source):
if self.files_to_skip_pattern.search(source):
return None
settings = self.document.settings
if os.path.exists(dest) and not settings.overwrite_theme_files:
settings.record_dependencies.add(dest)
else:
with open(source, 'rb') as src_file:
src_data = src_file.read()
with open(dest, 'wb') as dest_file:
dest_dir = dest_dir.replace(os.sep, '/')
dest_file.write(src_data.replace(
b'ui/default',
dest_dir[dest_dir.rfind('ui/'):].encode(
sys.getfilesystemencoding())))
settings.record_dependencies.add(source)
return True
if os.path.isfile(dest):
return True
def depart_document(self, node):
self.head_prefix.extend([self.doctype,
self.head_prefix_template %
{'lang': self.settings.language_code}])
self.html_prolog.append(self.doctype)
self.head = self.meta[:] + self.head
if self.math_header:
if self.math_output == 'mathjax':
self.head.extend(self.math_header)
else:
self.stylesheet.extend(self.math_header)
# skip content-type meta tag with interpolated charset value:
self.html_head.extend(self.head[1:])
self.fragment.extend(self.body)
# special S5 code up to the next comment line
header = ''.join(self.s5_header)
footer = ''.join(self.s5_footer)
title = ''.join(self.html_title).replace('<h1 class="title">', '<h1>')
layout = self.layout_template % {'header': header,
'title': title,
'footer': footer}
self.body_prefix.extend(layout)
self.body_prefix.append('<div class="presentation">\n')
self.body_prefix.append(
self.starttag({'classes': ['slide'], 'ids': ['slide0']}, 'div'))
if not self.section_count:
self.body.append('</div>\n')
#
self.body_suffix.insert(0, '</div>\n')
self.html_body.extend(self.body_prefix[1:] + self.body_pre_docinfo
+ self.docinfo + self.body
+ self.body_suffix[:-1])
def depart_footer(self, node):
start = self.context.pop()
self.s5_footer.append('<h2>')
self.s5_footer.extend(self.body[start:])
self.s5_footer.append('</h2>')
del self.body[start:]
def depart_header(self, node):
start = self.context.pop()
header = ['<div id="header">\n']
header.extend(self.body[start:])
header.append('\n</div>\n')
del self.body[start:]
self.s5_header.extend(header)
def visit_section(self, node):
if not self.section_count:
self.body.append('\n</div>\n')
self.section_count += 1
self.section_level += 1
if self.section_level > 1:
# dummy for matching div's
self.body.append(self.starttag(node, 'div', CLASS='section'))
else:
self.body.append(self.starttag(node, 'div', CLASS='slide'))
def visit_subtitle(self, node):
if isinstance(node.parent, nodes.section):
level = self.section_level + self.initial_header_level - 1
if level == 1:
level = 2
tag = 'h%s' % level
self.body.append(self.starttag(node, tag, ''))
self.context.append('</%s>\n' % tag)
else:
html4css1.HTMLTranslator.visit_subtitle(self, node)
def visit_title(self, node):
html4css1.HTMLTranslator.visit_title(self, node)

View file

@ -0,0 +1,6 @@
Except where otherwise noted, all files in this
directory have been released into the Public Domain.
These files are based on files from S5 1.1, released into the Public
Domain by Eric Meyer. For further details, please see
http://www.meyerweb.com/eric/tools/s5/credits.html.

View file

@ -0,0 +1,2 @@
# base theme of this theme:
big-white

View file

@ -0,0 +1,25 @@
/* The following styles size, place, and layer the slide components.
Edit these if you want to change the overall slide layout.
The commented lines can be uncommented (and modified, if necessary)
to help you with the rearrangement process. */
/* target = 1024x768 */
div#header, div#footer, .slide {width: 100%; top: 0; left: 0;}
div#header {top: 0; z-index: 1;}
div#footer {display:none;}
.slide {top: 0; width: 92%; padding: 0.1em 4% 4%; z-index: 2;}
/* list-style: none;} */
div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0;}
#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em;
z-index: 10;}
html>body #currentSlide {position: fixed;}
/*
div#header {background: #FCC;}
div#footer {background: #CCF;}
div#controls {background: #BBD;}
div#currentSlide {background: #FFC;}
*/

View file

@ -0,0 +1,109 @@
/* This file has been placed in the public domain. */
/* Following are the presentation styles -- edit away! */
html, body {margin: 0; padding: 0;}
body {background: black; color: white;}
:link, :visited {text-decoration: none; color: cyan;}
#controls :active {color: #888 !important;}
#controls :focus {outline: 1px dotted #CCC;}
blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em;}
blockquote p {margin: 0;}
kbd {font-weight: bold; font-size: 1em;}
sup {font-size: smaller; line-height: 1px;}
.slide pre {padding: 0; margin-left: 0; margin-right: 0; font-size: 90%;}
.slide ul ul li {list-style: square;}
.slide img.leader {display: block; margin: 0 auto;}
.slide tt {font-size: 90%;}
.slide {font-size: 3em; font-family: sans-serif; font-weight: bold;}
.slide h1 {padding-top: 0; z-index: 1; margin: 0; font-size: 120%;}
.slide h2 {font-size: 110%;}
.slide h3 {font-size: 105%;}
h1 abbr {font-variant: small-caps;}
div#controls {position: absolute; left: 50%; bottom: 0;
width: 50%; text-align: right; font: bold 0.9em sans-serif;}
html>body div#controls {position: fixed; padding: 0 0 1em 0; top: auto;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0; padding: 0;}
#controls #navLinks a {padding: 0; margin: 0 0.5em;
border: none; color: #888; cursor: pointer;}
#controls #navList {height: 1em;}
#controls #navList #jumplist {position: absolute; bottom: 0; right: 0;
background: black; color: #CCC;}
#currentSlide {text-align: center; font-size: 0.5em; color: #AAA;
font-family: sans-serif; font-weight: bold;}
#slide0 h1 {position: static; margin: 0 0 0.5em; padding-top: 0.3em; top: 0;
font-size: 150%; white-space: normal; background: transparent;}
#slide0 h2 {font: 110%; font-style: italic; color: gray;}
#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}
#slide0 h4 {margin-top: 0; font-size: 1em;}
ul.urls {list-style: none; display: inline; margin: 0;}
.urls li {display: inline; margin: 0;}
.external {border-bottom: 1px dotted gray;}
html>body .external {border-bottom: none;}
.external:after {content: " \274F"; font-size: smaller; color: #FCC;}
.incremental, .incremental *, .incremental *:after {
color: black; visibility: visible; border: 0;}
img.incremental {visibility: hidden;}
.slide .current {color: lime;}
.slide-display {display: inline ! important;}
.huge {font-size: 150%;}
.big {font-size: 120%;}
.small {font-size: 75%;}
.tiny {font-size: 50%;}
.huge tt, .big tt, .small tt, .tiny tt {font-size: 115%;}
.huge pre, .big pre, .small pre, .tiny pre {font-size: 115%;}
.maroon {color: maroon;}
.red {color: red;}
.magenta {color: magenta;}
.fuchsia {color: fuchsia;}
.pink {color: #FAA;}
.orange {color: orange;}
.yellow {color: yellow;}
.lime {color: lime;}
.green {color: green;}
.olive {color: olive;}
.teal {color: teal;}
.cyan {color: cyan;}
.aqua {color: aqua;}
.blue {color: blue;}
.navy {color: navy;}
.purple {color: purple;}
.black {color: black;}
.gray {color: gray;}
.silver {color: silver;}
.white {color: white;}
.left {text-align: left ! important;}
.center {text-align: center ! important;}
.right {text-align: right ! important;}
.animation {position: relative; margin: 1em 0; padding: 0;}
.animation img {position: absolute;}
/* Docutils-specific overrides */
.slide table.docinfo {margin: 0.5em 0 0.5em 1em;}
div.sidebar {background-color: black;}
pre.literal-block, pre.doctest-block {background-color: black;}
tt.docutils {background-color: black;}
/* diagnostics */
/*
li:after {content: " [" attr(class) "]"; color: #F88;}
div:before {content: "[" attr(class) "]"; color: #F88;}
*/

View file

@ -0,0 +1,24 @@
/* This file has been placed in the public domain. */
/* The following styles size, place, and layer the slide components.
Edit these if you want to change the overall slide layout.
The commented lines can be uncommented (and modified, if necessary)
to help you with the rearrangement process. */
/* target = 1024x768 */
div#header, div#footer, .slide {width: 100%; top: 0; left: 0;}
div#footer {display:none;}
.slide {top: 0; width: 92%; padding: 0.25em 4% 4%; z-index: 2;}
div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0;}
#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em;
z-index: 10;}
html>body #currentSlide {position: fixed;}
/*
div#header {background: #FCC;}
div#footer {background: #CCF;}
div#controls {background: #BBD;}
div#currentSlide {background: #FFC;}
*/

View file

@ -0,0 +1,107 @@
/* This file has been placed in the public domain. */
/* Following are the presentation styles -- edit away! */
html, body {margin: 0; padding: 0;}
body {background: white; color: black;}
:link, :visited {text-decoration: none; color: #00C;}
#controls :active {color: #88A !important;}
#controls :focus {outline: 1px dotted #227;}
blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em;}
blockquote p {margin: 0;}
kbd {font-weight: bold; font-size: 1em;}
sup {font-size: smaller; line-height: 1px;}
.slide pre {padding: 0; margin-left: 0; margin-right: 0; font-size: 90%;}
.slide ul ul li {list-style: square;}
.slide img.leader {display: block; margin: 0 auto;}
.slide tt {font-size: 90%;}
.slide {font-size: 3em; font-family: sans-serif; font-weight: bold;}
.slide h1 {padding-top: 0; z-index: 1; margin: 0; font-size: 120%;}
.slide h2 {font-size: 110%;}
.slide h3 {font-size: 105%;}
h1 abbr {font-variant: small-caps;}
div#controls {position: absolute; left: 50%; bottom: 0;
width: 50%; text-align: right; font: bold 0.9em sans-serif;}
html>body div#controls {position: fixed; padding: 0 0 1em 0; top: auto;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0; padding: 0;}
#controls #navLinks a {padding: 0; margin: 0 0.5em;
border: none; color: #005; cursor: pointer;}
#controls #navList {height: 1em;}
#controls #navList #jumplist {position: absolute; bottom: 0; right: 0;
background: #DDD; color: #227;}
#currentSlide {text-align: center; font-size: 0.5em; color: #444;
font-family: sans-serif; font-weight: bold;}
#slide0 h1 {position: static; margin: 0 0 0.5em; padding-top: 0.3em; top: 0;
font-size: 150%; white-space: normal; background: transparent;}
#slide0 h2 {font: 110%; font-style: italic; color: gray;}
#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}
#slide0 h4 {margin-top: 0; font-size: 1em;}
ul.urls {list-style: none; display: inline; margin: 0;}
.urls li {display: inline; margin: 0;}
.external {border-bottom: 1px dotted gray;}
html>body .external {border-bottom: none;}
.external:after {content: " \274F"; font-size: smaller; color: #77B;}
.incremental, .incremental *, .incremental *:after {
color: white; visibility: visible; border: 0;}
img.incremental {visibility: hidden;}
.slide .current {color: green;}
.slide-display {display: inline ! important;}
.huge {font-size: 150%;}
.big {font-size: 120%;}
.small {font-size: 75%;}
.tiny {font-size: 50%;}
.huge tt, .big tt, .small tt, .tiny tt {font-size: 115%;}
.huge pre, .big pre, .small pre, .tiny pre {font-size: 115%;}
.maroon {color: maroon;}
.red {color: red;}
.magenta {color: magenta;}
.fuchsia {color: fuchsia;}
.pink {color: #FAA;}
.orange {color: orange;}
.yellow {color: yellow;}
.lime {color: lime;}
.green {color: green;}
.olive {color: olive;}
.teal {color: teal;}
.cyan {color: cyan;}
.aqua {color: aqua;}
.blue {color: blue;}
.navy {color: navy;}
.purple {color: purple;}
.black {color: black;}
.gray {color: gray;}
.silver {color: silver;}
.white {color: white;}
.left {text-align: left ! important;}
.center {text-align: center ! important;}
.right {text-align: right ! important;}
.animation {position: relative; margin: 1em 0; padding: 0;}
.animation img {position: absolute;}
/* Docutils-specific overrides */
.slide table.docinfo {margin: 0.5em 0 0.5em 1em;}
pre.literal-block, pre.doctest-block {background-color: white;}
tt.docutils {background-color: white;}
/* diagnostics */
/*
li:after {content: " [" attr(class) "]"; color: #F88;}
div:before {content: "[" attr(class) "]"; color: #F88;}
*/

View file

@ -0,0 +1,25 @@
/* This file has been placed in the public domain. */
/* The following styles size, place, and layer the slide components.
Edit these if you want to change the overall slide layout.
The commented lines can be uncommented (and modified, if necessary)
to help you with the rearrangement process. */
/* target = 1024x768 */
div#header, div#footer, .slide {width: 100%; top: 0; left: 0;}
div#header {position: fixed; top: 0; height: 3em; z-index: 1;}
div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;}
.slide {top: 0; width: 92%; padding: 2.5em 4% 4%; z-index: 2;}
div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0;}
#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em;
z-index: 10;}
html>body #currentSlide {position: fixed;}
/*
div#header {background: #FCC;}
div#footer {background: #CCF;}
div#controls {background: #BBD;}
div#currentSlide {background: #FFC;}
*/

View file

@ -0,0 +1,8 @@
/* This file has been placed in the public domain. */
/* DO NOT CHANGE THESE unless you really want to break Opera Show */
.slide {
visibility: visible !important;
position: static !important;
page-break-before: always;
}
#slide0 {page-break-before: avoid;}

View file

@ -0,0 +1,16 @@
/* This file has been placed in the public domain. */
/* Don't change this unless you want the layout stuff to show up in the
outline view! */
.layout div, #footer *, #controlForm * {display: none;}
#footer, #controls, #controlForm, #navLinks, #toggle {
display: block; visibility: visible; margin: 0; padding: 0;}
#toggle {float: right; padding: 0.5em;}
html>body #toggle {position: fixed; top: 0; right: 0;}
/* making the outline look pretty-ish */
#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;}
#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;}
.outline {display: inline ! important;}

View file

@ -0,0 +1,120 @@
/* This file has been placed in the public domain. */
/* Following are the presentation styles -- edit away! */
html, body {margin: 0; padding: 0;}
body {background: white; color: black;}
/* Replace the background style above with the style below (and again for
div#header) for a graphic: */
/* background: white url(bodybg.gif) -16px 0 no-repeat; */
:link, :visited {text-decoration: none; color: #00C;}
#controls :active {color: #88A !important;}
#controls :focus {outline: 1px dotted #227;}
h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}
blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em;}
blockquote p {margin: 0;}
kbd {font-weight: bold; font-size: 1em;}
sup {font-size: smaller; line-height: 1px;}
.slide pre {padding: 0; margin-left: 0; margin-right: 0; font-size: 90%;}
.slide ul ul li {list-style: square;}
.slide img.leader {display: block; margin: 0 auto;}
.slide tt {font-size: 90%;}
div#header, div#footer {background: #005; color: #AAB; font-family: sans-serif;}
/* background: #005 url(bodybg.gif) -16px 0 no-repeat; */
div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;}
#footer h1 {display: block; padding: 0 1em;}
#footer h2 {display: block; padding: 0.8em 1em 0;}
.slide {font-size: 1.2em;}
.slide h1 {position: absolute; top: 0.45em; z-index: 1;
margin: 0; padding-left: 0.7em; white-space: nowrap;
font: bold 150% sans-serif; color: #DDE; background: #005;}
.slide h2 {font: bold 120%/1em sans-serif; padding-top: 0.5em;}
.slide h3 {font: bold 100% sans-serif; padding-top: 0.5em;}
h1 abbr {font-variant: small-caps;}
div#controls {position: absolute; left: 50%; bottom: 0;
width: 50%; text-align: right; font: bold 0.9em sans-serif;}
html>body div#controls {position: fixed; padding: 0 0 1em 0; top: auto;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0; padding: 0;}
#controls #navLinks a {padding: 0; margin: 0 0.5em;
background: #005; border: none; color: #779; cursor: pointer;}
#controls #navList {height: 1em;}
#controls #navList #jumplist {position: absolute; bottom: 0; right: 0;
background: #DDD; color: #227;}
#currentSlide {text-align: center; font-size: 0.5em; color: #449;
font-family: sans-serif; font-weight: bold;}
#slide0 {padding-top: 1.5em}
#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; color: #000;
font: bold 2em sans-serif; white-space: normal; background: transparent;}
#slide0 h2 {font: bold italic 1em sans-serif; margin: 0.25em;}
#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}
#slide0 h4 {margin-top: 0; font-size: 1em;}
ul.urls {list-style: none; display: inline; margin: 0;}
.urls li {display: inline; margin: 0;}
.external {border-bottom: 1px dotted gray;}
html>body .external {border-bottom: none;}
.external:after {content: " \274F"; font-size: smaller; color: #77B;}
.incremental, .incremental *, .incremental *:after {visibility: visible;
color: white; border: 0;}
img.incremental {visibility: hidden;}
.slide .current {color: green;}
.slide-display {display: inline ! important;}
.huge {font-family: sans-serif; font-weight: bold; font-size: 150%;}
.big {font-family: sans-serif; font-weight: bold; font-size: 120%;}
.small {font-size: 75%;}
.tiny {font-size: 50%;}
.huge tt, .big tt, .small tt, .tiny tt {font-size: 115%;}
.huge pre, .big pre, .small pre, .tiny pre {font-size: 115%;}
.maroon {color: maroon;}
.red {color: red;}
.magenta {color: magenta;}
.fuchsia {color: fuchsia;}
.pink {color: #FAA;}
.orange {color: orange;}
.yellow {color: yellow;}
.lime {color: lime;}
.green {color: green;}
.olive {color: olive;}
.teal {color: teal;}
.cyan {color: cyan;}
.aqua {color: aqua;}
.blue {color: blue;}
.navy {color: navy;}
.purple {color: purple;}
.black {color: black;}
.gray {color: gray;}
.silver {color: silver;}
.white {color: white;}
.left {text-align: left ! important;}
.center {text-align: center ! important;}
.right {text-align: right ! important;}
.animation {position: relative; margin: 1em 0; padding: 0;}
.animation img {position: absolute;}
/* Docutils-specific overrides */
.slide table.docinfo {margin: 1em 0 0.5em 2em;}
pre.literal-block, pre.doctest-block {background-color: white;}
tt.docutils {background-color: white;}
/* diagnostics */
/*
li:after {content: " [" attr(class) "]"; color: #F88;}
div:before {content: "[" attr(class) "]"; color: #F88;}
*/

View file

@ -0,0 +1,24 @@
/* This file has been placed in the public domain. */
/* The following rule is necessary to have all slides appear in print!
DO NOT REMOVE IT! */
.slide, ul {page-break-inside: avoid; visibility: visible !important;}
h1 {page-break-after: avoid;}
body {font-size: 12pt; background: white;}
* {color: black;}
#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}
#slide0 h3 {margin: 0; padding: 0;}
#slide0 h4 {margin: 0 0 0.5em; padding: 0;}
#slide0 {margin-bottom: 3em;}
#header {display: none;}
#footer h1 {margin: 0; border-bottom: 1px solid; color: gray;
font-style: italic;}
#footer h2, #controls {display: none;}
.print {display: inline ! important;}
/* The following rule keeps the layout stuff out of print.
Remove at your own risk! */
.layout, .layout * {display: none !important;}

View file

@ -0,0 +1,11 @@
/* This file has been placed in the public domain. */
/* Do not edit or override these styles!
The system will likely break if you do. */
div#header, div#footer, div#controls, .slide {position: absolute;}
html>body div#header, html>body div#footer,
html>body div#controls, html>body .slide {position: fixed;}
.handout {display: none;}
.layout {display: block;}
.slide, .hideme, .incremental {visibility: hidden;}
#slide0 {visibility: visible;}

View file

@ -0,0 +1,10 @@
/* This file has been placed in the public domain. */
/* required to make the slide show run at all */
@import url(s5-core.css);
/* sets basic placement and size of slide components */
@import url(framing.css);
/* styles that make the slides look good */
@import url(pretty.css);

View file

@ -0,0 +1,558 @@
// S5 v1.1 slides.js -- released into the Public Domain
// Modified for Docutils (https://docutils.sourceforge.io) by David Goodger
//
// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for
// information about all the wonderful and talented contributors to this code!
var undef;
var slideCSS = '';
var snum = 0;
var smax = 1;
var slideIDs = new Array();
var incpos = 0;
var number = undef;
var s5mode = true;
var defaultView = 'slideshow';
var controlVis = 'visible';
var isIE = navigator.appName == 'Microsoft Internet Explorer' ? 1 : 0;
var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0;
var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0;
function hasClass(object, className) {
if (!object.className) return false;
return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1);
}
function hasValue(object, value) {
if (!object) return false;
return (object.search('(^|\\s)' + value + '(\\s|$)') != -1);
}
function removeClass(object,className) {
if (!object) return;
object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2);
}
function addClass(object,className) {
if (!object || hasClass(object, className)) return;
if (object.className) {
object.className += ' '+className;
} else {
object.className = className;
}
}
function GetElementsWithClassName(elementName,className) {
var allElements = document.getElementsByTagName(elementName);
var elemColl = new Array();
for (var i = 0; i< allElements.length; i++) {
if (hasClass(allElements[i], className)) {
elemColl[elemColl.length] = allElements[i];
}
}
return elemColl;
}
function isParentOrSelf(element, id) {
if (element == null || element.nodeName=='BODY') return false;
else if (element.id == id) return true;
else return isParentOrSelf(element.parentNode, id);
}
function nodeValue(node) {
var result = "";
if (node.nodeType == 1) {
var children = node.childNodes;
for (var i = 0; i < children.length; ++i) {
result += nodeValue(children[i]);
}
}
else if (node.nodeType == 3) {
result = node.nodeValue;
}
return(result);
}
function slideLabel() {
var slideColl = GetElementsWithClassName('*','slide');
var list = document.getElementById('jumplist');
smax = slideColl.length;
for (var n = 0; n < smax; n++) {
var obj = slideColl[n];
var did = 'slide' + n.toString();
if (obj.getAttribute('id')) {
slideIDs[n] = obj.getAttribute('id');
}
else {
obj.setAttribute('id',did);
slideIDs[n] = did;
}
if (isOp) continue;
var otext = '';
var menu = obj.firstChild;
if (!menu) continue; // to cope with empty slides
while (menu && menu.nodeType == 3) {
menu = menu.nextSibling;
}
if (!menu) continue; // to cope with slides with only text nodes
var menunodes = menu.childNodes;
for (var o = 0; o < menunodes.length; o++) {
otext += nodeValue(menunodes[o]);
}
list.options[list.length] = new Option(n + ' : ' + otext, n);
}
}
function currentSlide() {
var cs;
var footer_nodes;
var vis = 'visible';
if (document.getElementById) {
cs = document.getElementById('currentSlide');
footer_nodes = document.getElementById('footer').childNodes;
} else {
cs = document.currentSlide;
footer = document.footer.childNodes;
}
cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' +
'<span id="csSep">\/<\/span> ' +
'<span id="csTotal">' + (smax-1) + '<\/span>';
if (snum == 0) {
vis = 'hidden';
}
cs.style.visibility = vis;
for (var i = 0; i < footer_nodes.length; i++) {
if (footer_nodes[i].nodeType == 1) {
footer_nodes[i].style.visibility = vis;
}
}
}
function go(step) {
if (document.getElementById('slideProj').disabled || step == 0) return;
var jl = document.getElementById('jumplist');
var cid = slideIDs[snum];
var ce = document.getElementById(cid);
if (incrementals[snum].length > 0) {
for (var i = 0; i < incrementals[snum].length; i++) {
removeClass(incrementals[snum][i], 'current');
removeClass(incrementals[snum][i], 'incremental');
}
}
if (step != 'j') {
snum += step;
lmax = smax - 1;
if (snum > lmax) snum = lmax;
if (snum < 0) snum = 0;
} else
snum = parseInt(jl.value);
var nid = slideIDs[snum];
var ne = document.getElementById(nid);
if (!ne) {
ne = document.getElementById(slideIDs[0]);
snum = 0;
}
if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;}
if (incrementals[snum].length > 0 && incpos == 0) {
for (var i = 0; i < incrementals[snum].length; i++) {
if (hasClass(incrementals[snum][i], 'current'))
incpos = i + 1;
else
addClass(incrementals[snum][i], 'incremental');
}
}
if (incrementals[snum].length > 0 && incpos > 0)
addClass(incrementals[snum][incpos - 1], 'current');
ce.style.visibility = 'hidden';
ne.style.visibility = 'visible';
jl.selectedIndex = snum;
currentSlide();
number = 0;
}
function goTo(target) {
if (target >= smax || target == snum) return;
go(target - snum);
}
function subgo(step) {
if (step > 0) {
removeClass(incrementals[snum][incpos - 1],'current');
removeClass(incrementals[snum][incpos], 'incremental');
addClass(incrementals[snum][incpos],'current');
incpos++;
} else {
incpos--;
removeClass(incrementals[snum][incpos],'current');
addClass(incrementals[snum][incpos], 'incremental');
addClass(incrementals[snum][incpos - 1],'current');
}
}
function toggle() {
var slideColl = GetElementsWithClassName('*','slide');
var slides = document.getElementById('slideProj');
var outline = document.getElementById('outlineStyle');
if (!slides.disabled) {
slides.disabled = true;
outline.disabled = false;
s5mode = false;
fontSize('1em');
for (var n = 0; n < smax; n++) {
var slide = slideColl[n];
slide.style.visibility = 'visible';
}
} else {
slides.disabled = false;
outline.disabled = true;
s5mode = true;
fontScale();
for (var n = 0; n < smax; n++) {
var slide = slideColl[n];
slide.style.visibility = 'hidden';
}
slideColl[snum].style.visibility = 'visible';
}
}
function showHide(action) {
var obj = GetElementsWithClassName('*','hideme')[0];
switch (action) {
case 's': obj.style.visibility = 'visible'; break;
case 'h': obj.style.visibility = 'hidden'; break;
case 'k':
if (obj.style.visibility != 'visible') {
obj.style.visibility = 'visible';
} else {
obj.style.visibility = 'hidden';
}
break;
}
}
// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/)
function keys(key) {
if (!key) {
key = event;
key.which = key.keyCode;
}
if (key.which == 84) {
toggle();
return;
}
if (s5mode) {
switch (key.which) {
case 10: // return
case 13: // enter
if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;
if (key.target && isParentOrSelf(key.target, 'controls')) return;
if(number != undef) {
goTo(number);
break;
}
case 32: // spacebar
case 34: // page down
case 39: // rightkey
case 40: // downkey
if(number != undef) {
go(number);
} else if (!incrementals[snum] || incpos >= incrementals[snum].length) {
go(1);
} else {
subgo(1);
}
break;
case 33: // page up
case 37: // leftkey
case 38: // upkey
if(number != undef) {
go(-1 * number);
} else if (!incrementals[snum] || incpos <= 0) {
go(-1);
} else {
subgo(-1);
}
break;
case 36: // home
goTo(0);
break;
case 35: // end
goTo(smax-1);
break;
case 67: // c
showHide('k');
break;
}
if (key.which < 48 || key.which > 57) {
number = undef;
} else {
if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;
if (key.target && isParentOrSelf(key.target, 'controls')) return;
number = (((number != undef) ? number : 0) * 10) + (key.which - 48);
}
}
return false;
}
function clicker(e) {
number = undef;
var target;
if (window.event) {
target = window.event.srcElement;
e = window.event;
} else target = e.target;
if (target.href != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target, 'object')) return true;
if (!e.which || e.which == 1) {
if (!incrementals[snum] || incpos >= incrementals[snum].length) {
go(1);
} else {
subgo(1);
}
}
}
function findSlide(hash) {
var target = document.getElementById(hash);
if (target) {
for (var i = 0; i < slideIDs.length; i++) {
if (target.id == slideIDs[i]) return i;
}
}
return null;
}
function slideJump() {
if (window.location.hash == null || window.location.hash == '') {
currentSlide();
return;
}
if (window.location.hash == null) return;
var dest = null;
dest = findSlide(window.location.hash.slice(1));
if (dest == null) {
dest = 0;
}
go(dest - snum);
}
function fixLinks() {
var thisUri = window.location.href;
thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length);
var aelements = document.getElementsByTagName('A');
for (var i = 0; i < aelements.length; i++) {
var a = aelements[i].href;
var slideID = a.match('\#.+');
if ((slideID) && (slideID[0].slice(0,1) == '#')) {
var dest = findSlide(slideID[0].slice(1));
if (dest != null) {
if (aelements[i].addEventListener) {
aelements[i].addEventListener("click", new Function("e",
"if (document.getElementById('slideProj').disabled) return;" +
"go("+dest+" - snum); " +
"if (e.preventDefault) e.preventDefault();"), true);
} else if (aelements[i].attachEvent) {
aelements[i].attachEvent("onclick", new Function("",
"if (document.getElementById('slideProj').disabled) return;" +
"go("+dest+" - snum); " +
"event.returnValue = false;"));
}
}
}
}
}
function externalLinks() {
if (!document.getElementsByTagName) return;
var anchors = document.getElementsByTagName('a');
for (var i=0; i<anchors.length; i++) {
var anchor = anchors[i];
if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) {
anchor.target = '_blank';
addClass(anchor,'external');
}
}
}
function createControls() {
var controlsDiv = document.getElementById("controls");
if (!controlsDiv) return;
var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"';
var hideDiv, hideList = '';
if (controlVis == 'hidden') {
hideDiv = hider;
} else {
hideList = hider;
}
controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' +
'<div id="navLinks">' +
'<a accesskey="t" id="toggle" href="javascript:toggle();">&#216;<\/a>' +
'<a accesskey="z" id="prev" href="javascript:go(-1);">&laquo;<\/a>' +
'<a accesskey="x" id="next" href="javascript:go(1);">&raquo;<\/a>' +
'<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' +
'<\/div><\/form>';
if (controlVis == 'hidden') {
var hidden = document.getElementById('navLinks');
} else {
var hidden = document.getElementById('jumplist');
}
addClass(hidden,'hideme');
}
function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers
if (!s5mode) return false;
var vScale = 22; // both yield 32 (after rounding) at 1024x768
var hScale = 32; // perhaps should auto-calculate based on theme's declared value?
if (window.innerHeight) {
var vSize = window.innerHeight;
var hSize = window.innerWidth;
} else if (document.documentElement.clientHeight) {
var vSize = document.documentElement.clientHeight;
var hSize = document.documentElement.clientWidth;
} else if (document.body.clientHeight) {
var vSize = document.body.clientHeight;
var hSize = document.body.clientWidth;
} else {
var vSize = 700; // assuming 1024x768, minus chrome and such
var hSize = 1024; // these do not account for kiosk mode or Opera Show
}
var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale));
fontSize(newSize + 'px');
if (isGe) { // hack to counter incremental reflow bugs
var obj = document.getElementsByTagName('body')[0];
obj.style.display = 'none';
obj.style.display = 'block';
}
}
function fontSize(value) {
if (!(s5ss = document.getElementById('s5ss'))) {
if (!isIE) {
document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style'));
s5ss.setAttribute('media','screen, projection');
s5ss.setAttribute('id','s5ss');
} else {
document.createStyleSheet();
document.s5ss = document.styleSheets[document.styleSheets.length - 1];
}
}
if (!isIE) {
while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild);
s5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}'));
} else {
document.s5ss.addRule('body','font-size: ' + value + ' !important;');
}
}
function notOperaFix() {
slideCSS = document.getElementById('slideProj').href;
var slides = document.getElementById('slideProj');
var outline = document.getElementById('outlineStyle');
slides.setAttribute('media','screen');
outline.disabled = true;
if (isGe) {
slides.setAttribute('href','null'); // Gecko fix
slides.setAttribute('href',slideCSS); // Gecko fix
}
if (isIE && document.styleSheets && document.styleSheets[0]) {
document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)');
document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)');
document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)');
}
}
function getIncrementals(obj) {
var incrementals = new Array();
if (!obj)
return incrementals;
var children = obj.childNodes;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (hasClass(child, 'incremental')) {
if (child.nodeName == 'OL' || child.nodeName == 'UL') {
removeClass(child, 'incremental');
for (var j = 0; j < child.childNodes.length; j++) {
if (child.childNodes[j].nodeType == 1) {
addClass(child.childNodes[j], 'incremental');
}
}
} else {
incrementals[incrementals.length] = child;
removeClass(child,'incremental');
}
}
if (hasClass(child, 'show-first')) {
if (child.nodeName == 'OL' || child.nodeName == 'UL') {
removeClass(child, 'show-first');
if (child.childNodes[isGe].nodeType == 1) {
removeClass(child.childNodes[isGe], 'incremental');
}
} else {
incrementals[incrementals.length] = child;
}
}
incrementals = incrementals.concat(getIncrementals(child));
}
return incrementals;
}
function createIncrementals() {
var incrementals = new Array();
for (var i = 0; i < smax; i++) {
incrementals[i] = getIncrementals(document.getElementById(slideIDs[i]));
}
return incrementals;
}
function defaultCheck() {
var allMetas = document.getElementsByTagName('meta');
for (var i = 0; i< allMetas.length; i++) {
if (allMetas[i].name == 'defaultView') {
defaultView = allMetas[i].content;
}
if (allMetas[i].name == 'controlVis') {
controlVis = allMetas[i].content;
}
}
}
// Key trap fix, new function body for trap()
function trap(e) {
if (!e) {
e = event;
e.which = e.keyCode;
}
try {
modifierKey = e.ctrlKey || e.altKey || e.metaKey;
}
catch(e) {
modifierKey = false;
}
return modifierKey || e.which == 0;
}
function startup() {
defaultCheck();
if (!isOp) createControls();
slideLabel();
fixLinks();
externalLinks();
fontScale();
if (!isOp) {
notOperaFix();
incrementals = createIncrementals();
slideJump();
if (defaultView == 'outline') {
toggle();
}
document.onkeyup = keys;
document.onkeypress = trap;
document.onclick = clicker;
}
}
window.onload = startup;
window.onresize = function(){setTimeout('fontScale()', 50);}

View file

@ -0,0 +1,2 @@
# base theme of this theme:
medium-white

View file

@ -0,0 +1,115 @@
/* This file has been placed in the public domain. */
/* Following are the presentation styles -- edit away! */
html, body {margin: 0; padding: 0;}
body {background: black; color: white;}
:link, :visited {text-decoration: none; color: cyan;}
#controls :active {color: #888 !important;}
#controls :focus {outline: 1px dotted #CCC;}
h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}
blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em;}
blockquote p {margin: 0;}
kbd {font-weight: bold; font-size: 1em;}
sup {font-size: smaller; line-height: 1px;}
.slide pre {padding: 0; margin-left: 0; margin-right: 0; font-size: 90%;}
.slide ul ul li {list-style: square;}
.slide img.leader {display: block; margin: 0 auto;}
.slide tt {font-size: 90%;}
div#footer {font-family: sans-serif; color: #AAA;
font-size: 0.5em; font-weight: bold; padding: 1em 0;}
#footer h1 {display: block; padding: 0 1em;}
#footer h2 {display: block; padding: 0.8em 1em 0;}
.slide {font-size: 1.75em;}
.slide h1 {padding-top: 0; z-index: 1; margin: 0; font: bold 150% sans-serif;}
.slide h2 {font: bold 125% sans-serif; padding-top: 0.5em;}
.slide h3 {font: bold 110% sans-serif; padding-top: 0.5em;}
h1 abbr {font-variant: small-caps;}
div#controls {position: absolute; left: 50%; bottom: 0;
width: 50%; text-align: right; font: bold 0.9em sans-serif;}
html>body div#controls {position: fixed; padding: 0 0 1em 0; top: auto;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0; padding: 0;}
#controls #navLinks a {padding: 0; margin: 0 0.5em;
border: none; color: #888; cursor: pointer;}
#controls #navList {height: 1em;}
#controls #navList #jumplist {position: absolute; bottom: 0; right: 0;
background: black; color: #CCC;}
#currentSlide {text-align: center; font-size: 0.5em; color: #AAA;
font-family: sans-serif; font-weight: bold;}
#slide0 h1 {position: static; margin: 0 0 0.5em; padding-top: 1em; top: 0;
font: bold 150% sans-serif; white-space: normal; background: transparent;}
#slide0 h2 {font: bold italic 125% sans-serif; color: gray;}
#slide0 h3 {margin-top: 1.5em; font: bold 110% sans-serif;}
#slide0 h4 {margin-top: 0; font-size: 1em;}
ul.urls {list-style: none; display: inline; margin: 0;}
.urls li {display: inline; margin: 0;}
.external {border-bottom: 1px dotted gray;}
html>body .external {border-bottom: none;}
.external:after {content: " \274F"; font-size: smaller; color: #FCC;}
.incremental, .incremental *, .incremental *:after {
color: black; visibility: visible; border: 0;}
img.incremental {visibility: hidden;}
.slide .current {color: lime;}
.slide-display {display: inline ! important;}
.huge {font-family: sans-serif; font-weight: bold; font-size: 150%;}
.big {font-family: sans-serif; font-weight: bold; font-size: 120%;}
.small {font-size: 75%;}
.tiny {font-size: 50%;}
.huge tt, .big tt, .small tt, .tiny tt {font-size: 115%;}
.huge pre, .big pre, .small pre, .tiny pre {font-size: 115%;}
.maroon {color: maroon;}
.red {color: red;}
.magenta {color: magenta;}
.fuchsia {color: fuchsia;}
.pink {color: #FAA;}
.orange {color: orange;}
.yellow {color: yellow;}
.lime {color: lime;}
.green {color: green;}
.olive {color: olive;}
.teal {color: teal;}
.cyan {color: cyan;}
.aqua {color: aqua;}
.blue {color: blue;}
.navy {color: navy;}
.purple {color: purple;}
.black {color: black;}
.gray {color: gray;}
.silver {color: silver;}
.white {color: white;}
.left {text-align: left ! important;}
.center {text-align: center ! important;}
.right {text-align: right ! important;}
.animation {position: relative; margin: 1em 0; padding: 0;}
.animation img {position: absolute;}
/* Docutils-specific overrides */
.slide table.docinfo {margin: 0.5em 0 0.5em 1em;}
div.sidebar {background-color: black;}
pre.literal-block, pre.doctest-block {background-color: black;}
tt.docutils {background-color: black;}
/* diagnostics */
/*
li:after {content: " [" attr(class) "]"; color: #F88;}
div:before {content: "[" attr(class) "]"; color: #F88;}
*/

View file

@ -0,0 +1,24 @@
/* This file has been placed in the public domain. */
/* The following styles size, place, and layer the slide components.
Edit these if you want to change the overall slide layout.
The commented lines can be uncommented (and modified, if necessary)
to help you with the rearrangement process. */
/* target = 1024x768 */
div#header, div#footer, .slide {width: 100%; top: 0; left: 0;}
div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;}
.slide {top: 0; width: 92%; padding: 0.75em 4% 0 4%; z-index: 2;}
div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0;}
#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em;
z-index: 10;}
html>body #currentSlide {position: fixed;}
/*
div#header {background: #FCC;}
div#footer {background: #CCF;}
div#controls {background: #BBD;}
div#currentSlide {background: #FFC;}
*/

View file

@ -0,0 +1,113 @@
/* This file has been placed in the public domain. */
/* Following are the presentation styles -- edit away! */
html, body {margin: 0; padding: 0;}
body {background: white; color: black;}
:link, :visited {text-decoration: none; color: #00C;}
#controls :active {color: #888 !important;}
#controls :focus {outline: 1px dotted #222;}
h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}
blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em;}
blockquote p {margin: 0;}
kbd {font-weight: bold; font-size: 1em;}
sup {font-size: smaller; line-height: 1px;}
.slide pre {padding: 0; margin-left: 0; margin-right: 0; font-size: 90%;}
.slide ul ul li {list-style: square;}
.slide img.leader {display: block; margin: 0 auto;}
.slide tt {font-size: 90%;}
div#footer {font-family: sans-serif; color: #444;
font-size: 0.5em; font-weight: bold; padding: 1em 0;}
#footer h1 {display: block; padding: 0 1em;}
#footer h2 {display: block; padding: 0.8em 1em 0;}
.slide {font-size: 1.75em;}
.slide h1 {padding-top: 0; z-index: 1; margin: 0; font: bold 150% sans-serif;}
.slide h2 {font: bold 125% sans-serif; padding-top: 0.5em;}
.slide h3 {font: bold 110% sans-serif; padding-top: 0.5em;}
h1 abbr {font-variant: small-caps;}
div#controls {position: absolute; left: 50%; bottom: 0;
width: 50%; text-align: right; font: bold 0.9em sans-serif;}
html>body div#controls {position: fixed; padding: 0 0 1em 0; top: auto;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0; padding: 0;}
#controls #navLinks a {padding: 0; margin: 0 0.5em;
border: none; color: #888; cursor: pointer;}
#controls #navList {height: 1em;}
#controls #navList #jumplist {position: absolute; bottom: 0; right: 0;
background: #DDD; color: #222;}
#currentSlide {text-align: center; font-size: 0.5em; color: #444;
font-family: sans-serif; font-weight: bold;}
#slide0 h1 {position: static; margin: 0 0 0.5em; padding-top: 1em; top: 0;
font: bold 150% sans-serif; white-space: normal; background: transparent;}
#slide0 h2 {font: bold italic 125% sans-serif; color: gray;}
#slide0 h3 {margin-top: 1.5em; font: bold 110% sans-serif;}
#slide0 h4 {margin-top: 0; font-size: 1em;}
ul.urls {list-style: none; display: inline; margin: 0;}
.urls li {display: inline; margin: 0;}
.external {border-bottom: 1px dotted gray;}
html>body .external {border-bottom: none;}
.external:after {content: " \274F"; font-size: smaller; color: #77B;}
.incremental, .incremental *, .incremental *:after {
color: white; visibility: visible; border: 0;}
img.incremental {visibility: hidden;}
.slide .current {color: green;}
.slide-display {display: inline ! important;}
.huge {font-family: sans-serif; font-weight: bold; font-size: 150%;}
.big {font-family: sans-serif; font-weight: bold; font-size: 120%;}
.small {font-size: 75%;}
.tiny {font-size: 50%;}
.huge tt, .big tt, .small tt, .tiny tt {font-size: 115%;}
.huge pre, .big pre, .small pre, .tiny pre {font-size: 115%;}
.maroon {color: maroon;}
.red {color: red;}
.magenta {color: magenta;}
.fuchsia {color: fuchsia;}
.pink {color: #FAA;}
.orange {color: orange;}
.yellow {color: yellow;}
.lime {color: lime;}
.green {color: green;}
.olive {color: olive;}
.teal {color: teal;}
.cyan {color: cyan;}
.aqua {color: aqua;}
.blue {color: blue;}
.navy {color: navy;}
.purple {color: purple;}
.black {color: black;}
.gray {color: gray;}
.silver {color: silver;}
.white {color: white;}
.left {text-align: left ! important;}
.center {text-align: center ! important;}
.right {text-align: right ! important;}
.animation {position: relative; margin: 1em 0; padding: 0;}
.animation img {position: absolute;}
/* Docutils-specific overrides */
.slide table.docinfo {margin: 0.5em 0 0.5em 1em;}
pre.literal-block, pre.doctest-block {background-color: white;}
tt.docutils {background-color: white;}
/* diagnostics */
/*
li:after {content: " [" attr(class) "]"; color: #F88;}
div:before {content: "[" attr(class) "]"; color: #F88;}
*/

View file

@ -0,0 +1,2 @@
# base theme of this theme:
small-white

View file

@ -0,0 +1,116 @@
/* This file has been placed in the public domain. */
/* Following are the presentation styles -- edit away! */
html, body {margin: 0; padding: 0;}
body {background: black; color: white;}
:link, :visited {text-decoration: none; color: cyan;}
#controls :active {color: #888 !important;}
#controls :focus {outline: 1px dotted #CCC;}
h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}
blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em;}
blockquote p {margin: 0;}
kbd {font-weight: bold; font-size: 1em;}
sup {font-size: smaller; line-height: 1px;}
.slide pre {padding: 0; margin-left: 0; margin-right: 0; font-size: 90%;}
.slide ul ul li {list-style: square;}
.slide img.leader {display: block; margin: 0 auto;}
.slide tt {font-size: 90%;}
div#footer {font-family: sans-serif; color: #AAA;
font-size: 0.5em; font-weight: bold; padding: 1em 0;}
#footer h1 {display: block; padding: 0 1em;}
#footer h2 {display: block; padding: 0.8em 1em 0;}
.slide {font-size: 1.2em;}
.slide h1 {padding-top: 0; z-index: 1; margin: 0; font: bold 150% sans-serif;}
.slide h2 {font: bold 120% sans-serif; padding-top: 0.5em;}
.slide h3 {font: bold 100% sans-serif; padding-top: 0.5em;}
h1 abbr {font-variant: small-caps;}
div#controls {position: absolute; left: 50%; bottom: 0;
width: 50%; text-align: right; font: bold 0.9em sans-serif;}
html>body div#controls {position: fixed; padding: 0 0 1em 0; top: auto;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0; padding: 0;}
#controls #navLinks a {padding: 0; margin: 0 0.5em;
border: none; color: #888; cursor: pointer;}
#controls #navList {height: 1em;}
#controls #navList #jumplist {position: absolute; bottom: 0; right: 0;
background: black; color: #CCC;}
#currentSlide {text-align: center; font-size: 0.5em; color: #AAA;
font-family: sans-serif; font-weight: bold;}
#slide0 {padding-top: 0em}
#slide0 h1 {position: static; margin: 1em 0 0; padding: 0;
font: bold 2em sans-serif; white-space: normal; background: transparent;}
#slide0 h2 {font: bold italic 1em sans-serif; margin: 0.25em;}
#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}
#slide0 h4 {margin-top: 0; font-size: 1em;}
ul.urls {list-style: none; display: inline; margin: 0;}
.urls li {display: inline; margin: 0;}
.external {border-bottom: 1px dotted gray;}
html>body .external {border-bottom: none;}
.external:after {content: " \274F"; font-size: smaller; color: #FCC;}
.incremental, .incremental *, .incremental *:after {
color: black; visibility: visible; border: 0;}
img.incremental {visibility: hidden;}
.slide .current {color: lime;}
.slide-display {display: inline ! important;}
.huge {font-family: sans-serif; font-weight: bold; font-size: 150%;}
.big {font-family: sans-serif; font-weight: bold; font-size: 120%;}
.small {font-size: 75%;}
.tiny {font-size: 50%;}
.huge tt, .big tt, .small tt, .tiny tt {font-size: 115%;}
.huge pre, .big pre, .small pre, .tiny pre {font-size: 115%;}
.maroon {color: maroon;}
.red {color: red;}
.magenta {color: magenta;}
.fuchsia {color: fuchsia;}
.pink {color: #FAA;}
.orange {color: orange;}
.yellow {color: yellow;}
.lime {color: lime;}
.green {color: green;}
.olive {color: olive;}
.teal {color: teal;}
.cyan {color: cyan;}
.aqua {color: aqua;}
.blue {color: blue;}
.navy {color: navy;}
.purple {color: purple;}
.black {color: black;}
.gray {color: gray;}
.silver {color: silver;}
.white {color: white;}
.left {text-align: left ! important;}
.center {text-align: center ! important;}
.right {text-align: right ! important;}
.animation {position: relative; margin: 1em 0; padding: 0;}
.animation img {position: absolute;}
/* Docutils-specific overrides */
.slide table.docinfo {margin: 1em 0 0.5em 2em;}
div.sidebar {background-color: black;}
pre.literal-block, pre.doctest-block {background-color: black;}
tt.docutils {background-color: black;}
/* diagnostics */
/*
li:after {content: " [" attr(class) "]"; color: #F88;}
div:before {content: "[" attr(class) "]"; color: #F88;}
*/

View file

@ -0,0 +1,24 @@
/* This file has been placed in the public domain. */
/* The following styles size, place, and layer the slide components.
Edit these if you want to change the overall slide layout.
The commented lines can be uncommented (and modified, if necessary)
to help you with the rearrangement process. */
/* target = 1024x768 */
div#header, div#footer, .slide {width: 100%; top: 0; left: 0;}
div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;}
.slide {top: 0; width: 92%; padding: 1em 4% 0 4%; z-index: 2;}
div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0;}
#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em;
z-index: 10;}
html>body #currentSlide {position: fixed;}
/*
div#header {background: #FCC;}
div#footer {background: #CCF;}
div#controls {background: #BBD;}
div#currentSlide {background: #FFC;}
*/

View file

@ -0,0 +1,114 @@
/* This file has been placed in the public domain. */
/* Following are the presentation styles -- edit away! */
html, body {margin: 0; padding: 0;}
body {background: white; color: black;}
:link, :visited {text-decoration: none; color: #00C;}
#controls :active {color: #888 !important;}
#controls :focus {outline: 1px dotted #222;}
h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}
blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em;}
blockquote p {margin: 0;}
kbd {font-weight: bold; font-size: 1em;}
sup {font-size: smaller; line-height: 1px;}
.slide pre {padding: 0; margin-left: 0; margin-right: 0; font-size: 90%;}
.slide ul ul li {list-style: square;}
.slide img.leader {display: block; margin: 0 auto;}
.slide tt {font-size: 90%;}
div#footer {font-family: sans-serif; color: #444;
font-size: 0.5em; font-weight: bold; padding: 1em 0;}
#footer h1 {display: block; padding: 0 1em;}
#footer h2 {display: block; padding: 0.8em 1em 0;}
.slide {font-size: 1.2em;}
.slide h1 {padding-top: 0; z-index: 1; margin: 0; font: bold 150% sans-serif;}
.slide h2 {font: bold 120% sans-serif; padding-top: 0.5em;}
.slide h3 {font: bold 100% sans-serif; padding-top: 0.5em;}
h1 abbr {font-variant: small-caps;}
div#controls {position: absolute; left: 50%; bottom: 0;
width: 50%; text-align: right; font: bold 0.9em sans-serif;}
html>body div#controls {position: fixed; padding: 0 0 1em 0; top: auto;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0; padding: 0;}
#controls #navLinks a {padding: 0; margin: 0 0.5em;
border: none; color: #888; cursor: pointer;}
#controls #navList {height: 1em;}
#controls #navList #jumplist {position: absolute; bottom: 0; right: 0;
background: #DDD; color: #222;}
#currentSlide {text-align: center; font-size: 0.5em; color: #444;
font-family: sans-serif; font-weight: bold;}
#slide0 {padding-top: 0em}
#slide0 h1 {position: static; margin: 1em 0 0; padding: 0;
font: bold 2em sans-serif; white-space: normal; background: transparent;}
#slide0 h2 {font: bold italic 1em sans-serif; margin: 0.25em;}
#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}
#slide0 h4 {margin-top: 0; font-size: 1em;}
ul.urls {list-style: none; display: inline; margin: 0;}
.urls li {display: inline; margin: 0;}
.external {border-bottom: 1px dotted gray;}
html>body .external {border-bottom: none;}
.external:after {content: " \274F"; font-size: smaller; color: #77B;}
.incremental, .incremental *, .incremental *:after {
color: white; visibility: visible; border: 0; border: 0;}
img.incremental {visibility: hidden;}
.slide .current {color: green;}
.slide-display {display: inline ! important;}
.huge {font-family: sans-serif; font-weight: bold; font-size: 150%;}
.big {font-family: sans-serif; font-weight: bold; font-size: 120%;}
.small {font-size: 75%;}
.tiny {font-size: 50%;}
.huge tt, .big tt, .small tt, .tiny tt {font-size: 115%;}
.huge pre, .big pre, .small pre, .tiny pre {font-size: 115%;}
.maroon {color: maroon;}
.red {color: red;}
.magenta {color: magenta;}
.fuchsia {color: fuchsia;}
.pink {color: #FAA;}
.orange {color: orange;}
.yellow {color: yellow;}
.lime {color: lime;}
.green {color: green;}
.olive {color: olive;}
.teal {color: teal;}
.cyan {color: cyan;}
.aqua {color: aqua;}
.blue {color: blue;}
.navy {color: navy;}
.purple {color: purple;}
.black {color: black;}
.gray {color: gray;}
.silver {color: silver;}
.white {color: white;}
.left {text-align: left ! important;}
.center {text-align: center ! important;}
.right {text-align: right ! important;}
.animation {position: relative; margin: 1em 0; padding: 0;}
.animation img {position: absolute;}
/* Docutils-specific overrides */
.slide table.docinfo {margin: 1em 0 0.5em 2em;}
pre.literal-block, pre.doctest-block {background-color: white;}
tt.docutils {background-color: white;}
/* diagnostics */
/*
li:after {content: " [" attr(class) "]"; color: #F88;}
div:before {content: "[" attr(class) "]"; color: #F88;}
*/

View file

@ -0,0 +1,147 @@
#!/usr/bin/env python3
# :Author: Günter Milde <milde@users.sf.net>
# :Revision: $Revision: 9293 $
# :Date: $Date: 2022-12-01 22:13:54 +0100 (Do, 01. Dez 2022) $
# :Copyright: © 2010 Günter Milde.
# :License: Released under the terms of the `2-Clause BSD license`_, in short:
#
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.
# This file is offered as-is, without any warranty.
#
# .. _2-Clause BSD license: https://opensource.org/licenses/BSD-2-Clause
"""
XeLaTeX document tree Writer.
A variant of Docutils' standard 'latex2e' writer producing LaTeX output
suited for processing with the Unicode-aware TeX engines
LuaTeX and XeTeX.
"""
__docformat__ = 'reStructuredText'
from docutils import frontend
from docutils.writers import latex2e
class Writer(latex2e.Writer):
"""A writer for Unicode-aware LaTeX variants (XeTeX, LuaTeX)"""
supported = ('latex', 'tex', 'xetex', 'xelatex', 'luatex', 'lualatex')
"""Formats this writer supports."""
default_template = 'xelatex.tex'
default_preamble = """\
% Linux Libertine (free, wide coverage, not only for Linux)
\\setmainfont{Linux Libertine O}
\\setsansfont{Linux Biolinum O}
\\setmonofont[HyphenChar=None,Scale=MatchLowercase]{DejaVu Sans Mono}"""
config_section = 'xetex writer'
config_section_dependencies = ('writers', 'latex writers')
# use a copy of the parent spec with some modifications:
settings_spec = frontend.filter_settings_spec(
latex2e.Writer.settings_spec,
# removed settings
'font_encoding',
# changed settings:
template=('Template file. Default: "%s".' % default_template,
['--template'],
{'default': default_template, 'metavar': '<file>'}),
latex_preamble=('Customization by LaTeX code in the preamble. '
'Default: select "Linux Libertine" fonts.',
['--latex-preamble'],
{'default': default_preamble}),
)
def __init__(self):
latex2e.Writer.__init__(self)
self.settings_defaults.update({'fontencoding': ''}) # use default (TU)
self.translator_class = XeLaTeXTranslator
class Babel(latex2e.Babel):
"""Language specifics for XeTeX.
Use `polyglossia` instead of `babel` and adapt settings.
"""
language_codes = latex2e.Babel.language_codes.copy()
# Additionally supported or differently named languages:
language_codes.update({
# code Polyglossia-name comment
'cop': 'coptic',
'de': 'german', # new spelling (de_1996)
'de-1901': 'ogerman', # old spelling
'dv': 'divehi', # Maldivian
'dsb': 'lsorbian',
'el-polyton': 'polygreek',
'fa': 'farsi',
'grc': 'ancientgreek',
'ko': 'korean',
'hsb': 'usorbian',
'sh-Cyrl': 'serbian', # Serbo-Croatian, Cyrillic script
'sh-Latn': 'croatian', # Serbo-Croatian, Latin script
'sq': 'albanian',
'sr': 'serbian', # Cyrillic script (sr-Cyrl)
'th': 'thai',
'vi': 'vietnamese',
# zh-Latn: ??? # Chinese Pinyin
})
# normalize (downcase) keys
language_codes = {k.lower(): v for k, v in language_codes.items()}
# Languages without Polyglossia support:
for key in ('af', # 'afrikaans',
'de-AT', # 'naustrian',
'de-AT-1901', # 'austrian',
# TODO: use variant=... for English variants
'en-CA', # 'canadian',
'en-GB', # 'british',
'en-NZ', # 'newzealand',
'en-US', # 'american',
'fr-CA', # 'canadien',
'grc-ibycus', # 'ibycus', (Greek Ibycus encoding)
'sr-Latn', # 'serbian script=latin'
):
del language_codes[key.lower()]
def __init__(self, language_code, reporter):
self.language_code = language_code
self.reporter = reporter
self.language = self.language_name(language_code)
self.otherlanguages = {}
self.warn_msg = 'Language "%s" not supported by Polyglossia.'
self.quote_index = 0
self.quotes = ('"', '"')
# language dependent configuration:
# double quotes are "active" in some languages (e.g. German).
self.literal_double_quote = '"' # TODO: use \textquotedbl ?
def __call__(self):
setup = [r'\usepackage{polyglossia}',
r'\setdefaultlanguage{%s}' % self.language]
if self.otherlanguages:
setup.append(r'\setotherlanguages{%s}' %
','.join(sorted(self.otherlanguages.keys())))
return '\n'.join(setup)
class XeLaTeXTranslator(latex2e.LaTeXTranslator):
"""
Generate code for LaTeX using Unicode fonts (XeLaTex or LuaLaTeX).
See the docstring of docutils.writers._html_base.HTMLTranslator for
notes on and examples of safe subclassing.
"""
def __init__(self, document):
self.is_xetex = True # typeset with XeTeX or LuaTeX engine
latex2e.LaTeXTranslator.__init__(self, document, Babel)
if self.latex_encoding == 'utf8':
self.requirements.pop('_inputenc', None)
else:
self.requirements['_inputenc'] = (r'\XeTeXinputencoding %s '
% self.latex_encoding)